-
Jaime Pérez authored
Now we are finally using the 2.x branch of the SAML2 library, which was also migrated to use namespaces. Even though the library provides an autoloader that allows loading the classes with the old names using class aliasing, we need to do the migration in one commit (at least for most part of it). This is due to the way SimpleSAMLphp checks data types, using inheritance to check objects agains abstract or more general classes. Even though class aliasing works, there's no way to replicate those relationships, and type checks that use the old class names will fail because the aliases are virtually new classes that don't inherit from others.
Jaime Pérez authoredNow we are finally using the 2.x branch of the SAML2 library, which was also migrated to use namespaces. Even though the library provides an autoloader that allows loading the classes with the old names using class aliasing, we need to do the migration in one commit (at least for most part of it). This is due to the way SimpleSAMLphp checks data types, using inheritance to check objects agains abstract or more general classes. Even though class aliasing works, there's no way to replicate those relationships, and type checks that use the old class names will fail because the aliases are virtually new classes that don't inherit from others.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
SQLPersistentNameID.php 5.52 KiB
<?php
/**
* Authentication processing filter to generate a persistent NameID.
*
* @package SimpleSAMLphp
*/
class sspmod_saml_Auth_Process_SQLPersistentNameID extends sspmod_saml_BaseNameIDGenerator
{
/**
* Which attribute contains the unique identifier of the user.
*
* @var string
*/
private $attribute;
/**
* Whether we should create a persistent NameID if not explicitly requested (as saml:PersistentNameID does).
*
* @var boolean
*/
private $allowUnspecified = false;
/**
* Whether we should create a persistent NameID if a different format is requested.
*
* @var boolean
*/
private $allowDifferent = false;
/**
* Whether we should ignore allowCreate in the NameID policy
*
* @var boolean
*/
private $alwaysCreate = false;
/**
* Initialize this filter, parse configuration.
*
* @param array $config Configuration information about this filter.
* @param mixed $reserved For future use.
*
* @throws SimpleSAML_Error_Exception If the 'attribute' option is not specified.
*/
public function __construct($config, $reserved)
{
parent::__construct($config, $reserved);
assert('is_array($config)');
$this->format = \SAML2\Constants::NAMEID_PERSISTENT;
if (!isset($config['attribute'])) {
throw new SimpleSAML_Error_Exception("PersistentNameID: Missing required option 'attribute'.");
}
$this->attribute = $config['attribute'];
if (isset($config['allowUnspecified'])) {
$this->allowUnspecified = (bool) $config['allowUnspecified'];
}
if (isset($config['allowDifferent'])) {
$this->allowDifferent = (bool) $config['allowDifferent'];
}
if (isset($config['alwaysCreate'])) {
$this->alwaysCreate = (bool) $config['alwaysCreate'];
}
}
/**
* Get the NameID value.
*
* @param array $state The state array.
* @return string|null The NameID value.
*
* @throws sspmod_saml_Error if the NameID creation policy is invalid.
*/
protected function getValue(array &$state)
{
if (!isset($state['saml:NameIDFormat']) && !$this->allowUnspecified) {
SimpleSAML\Logger::debug(
'SQLPersistentNameID: Request did not specify persistent NameID format, '.
'not generating persistent NameID.'
);
return null;
}
$validNameIdFormats = @array_filter(array(
$state['saml:NameIDFormat'],
$state['SPMetadata']['NameIDPolicy'],
$state['SPMetadata']['NameIDFormat']
));
if (count($validNameIdFormats) && !in_array($this->format, $validNameIdFormats) && !$this->allowDifferent) {
SimpleSAML\Logger::debug(
'SQLPersistentNameID: SP expects different NameID format ('.
implode(', ', $validNameIdFormats).'), not generating persistent NameID.'
);
return null;
}
if (!isset($state['Destination']['entityid'])) {
SimpleSAML\Logger::warning('SQLPersistentNameID: No SP entity ID - not generating persistent NameID.');
return null;
}
$spEntityId = $state['Destination']['entityid'];
if (!isset($state['Source']['entityid'])) {
SimpleSAML\Logger::warning('SQLPersistentNameID: No IdP entity ID - not generating persistent NameID.');
return null;
}
$idpEntityId = $state['Source']['entityid'];
if (!isset($state['Attributes'][$this->attribute]) || count($state['Attributes'][$this->attribute]) === 0) {
SimpleSAML\Logger::warning(
'SQLPersistentNameID: Missing attribute '.var_export($this->attribute, true).
' on user - not generating persistent NameID.'
);
return null;
}
if (count($state['Attributes'][$this->attribute]) > 1) {
SimpleSAML\Logger::warning(
'SQLPersistentNameID: More than one value in attribute '.var_export($this->attribute, true).
' on user - not generating persistent NameID.'
);
return null;
}
$uid = array_values($state['Attributes'][$this->attribute]); // just in case the first index is no longer 0
$uid = $uid[0];
$value = sspmod_saml_IdP_SQLNameID::get($idpEntityId, $spEntityId, $uid);
if ($value !== null) {
SimpleSAML\Logger::debug(
'SQLPersistentNameID: Found persistent NameID '.var_export($value, true).' for user '.
var_export($uid, true).'.'
);
return $value;
}
if ((!isset($state['saml:AllowCreate']) || !$state['saml:AllowCreate']) && !$this->alwaysCreate) {
SimpleSAML\Logger::warning(
'SQLPersistentNameID: Did not find persistent NameID for user, and not allowed to create new NameID.'
);
throw new sspmod_saml_Error(
\SAML2\Constants::STATUS_RESPONDER,
'urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy'
);
}
$value = bin2hex(openssl_random_pseudo_bytes(20));
SimpleSAML\Logger::debug(
'SQLPersistentNameID: Created persistent NameID '.var_export($value, true).' for user '.
var_export($uid, true).'.'
);
sspmod_saml_IdP_SQLNameID::add($idpEntityId, $spEntityId, $uid, $value);
return $value;
}
}