diff --git a/docs/simplesamlphp-authproc.txt b/docs/simplesamlphp-authproc.txt index 7b3b08d9dec6ce63cac7bf5089ca562df5a11eea..da1500f0134219be7d48300defe5fa127ee44bd7 100644 --- a/docs/simplesamlphp-authproc.txt +++ b/docs/simplesamlphp-authproc.txt @@ -148,6 +148,7 @@ The following filters are included in the simpleSAMLphp distribution: - [`saml:NameIDAttribute`](./saml:nameidattribute): Create an attribute based on the NameID we receive from the IdP. - [`saml:PersistentNameID`](./saml:nameid): Generate persistent NameID from an attribute. - [`saml:TransientNameID`](./saml:nameid): Generate transient NameID. +- [`smartattributes:SmartID`](./smartattributes:smartattributes): Generate user ID attribute based on several attributes. diff --git a/modules/smartattributes/docs/smartattributes.txt b/modules/smartattributes/docs/smartattributes.txt new file mode 100644 index 0000000000000000000000000000000000000000..fbee41c6ff915febe1767142c67afd625a48bb2e --- /dev/null +++ b/modules/smartattributes/docs/smartattributes.txt @@ -0,0 +1,68 @@ +SmartAttributes module +====================== + +The SmartAttributes module provides authentication processing filters that add attributes. +The logic in these filters exceeds what is possible with the standard filters such as [`core:AttributeAdd`], [`core:AttributeAlter`], and [`core:AttributeMap`]. + + + +`smartattributes:SmartID` +========================= + +Filter to add an identifier attribute, based on the first non-empty attribute from a given list of attribute names. +This is usefull when there are multiple SAML IdPs configured, and there is no common identifier among them. +For example some IdPs sent eduPersonPrincipalName, while others sent eduPersonTargetedID. If any of the social network are configured as authsource, they will sent yet another identifier. +The filter has the following configuration options: + +* `candidates`. An array of attributes names to consider as the identifier attribute. Defaults to: + * eduPersonTargetedID + * eduPersonPrincipalName + * openid + * facebook_targetedID + * twitter_targetedID + * windowslive_targetedID + * myspace_targetedID + * linkedin_targetedID +* `id_attribute`. A string to use as the name of the newly added attribute. Defaults to `smart_id`. +* `add_authority`. A boolean to indicate whether or not to append the SAML AuthenticatingAuthority to the resulting identifier. This can be useful to indicate what SAML IdP was used, in case the original identifier is not scoped. Defaults to `true`. + +The generated identifiers have the form: + +`AttributeName:AttributeValue!AuthenticatingAuthority` + +For example: + +`eduPersonTargetedID:c4bcbe7ca8eac074f65291fd5524caa88f3115c8!https://login.terena.org/idp/saml2/idp/metadata.php` + +Examples +-------- + +Without any configuration: + + 'authproc' => array( + 50 => array( + 'class' => 'smartattributes:SmartID' + ), + ), + + +This will add an attribute called `smart_id` with this value: + +`eduPersonTargetedID:c4bcbe7ca8eac074f65291fd5524caa88f3115c8!https://login.terena.org/idp/saml2/idp/metadata.php` + + +Custom configuration: + + 'authproc' => array( + 50 => array( + 'class' => 'smartattributes:SmartID', + 'candidates' => array('eduPersonTargetedID', 'eduPersonPrincipalName'), + 'id_attribute' => 'FooUniversityLocalID', + 'add_authority' => false + ), + ), + +This will add an attribute called `FooUniversityLocalID` with this value: + +`eduPersonTargetedID:c4bcbe7ca8eac074f65291fd5524caa88f3115c8` + diff --git a/modules/smartattributes/lib/Auth/Process/SmartID.php b/modules/smartattributes/lib/Auth/Process/SmartID.php new file mode 100644 index 0000000000000000000000000000000000000000..2520bf8288efb805621cacd0a27a8cf6c468b642 --- /dev/null +++ b/modules/smartattributes/lib/Auth/Process/SmartID.php @@ -0,0 +1,105 @@ +<?php + +class sspmod_smartattributes_Auth_Process_SmartID extends SimpleSAML_Auth_ProcessingFilter { + + /** + * Which attributes to use as identifiers? + * + * IMPORTANT: If you use the (default) attributemaps (twitter2name, facebook2name, + * etc., be sure to comment out the entries that map xxx_targetedID to + * eduPersonTargetedID, or there will be no way to see its origin any more. + */ + private $_candidates = array( + 'eduPersonTargetedID', + 'eduPersonPrincipalName', + 'openid', + 'facebook_targetedID', + 'twitter_targetedID', + 'windowslive_targetedID', + 'myspace_targetedID', + 'linkedin_targetedID', + ); + + /** + * The name of the generated ID attribute. + */ + private $_id_attribute = 'smart_id'; + + /** + * Whether to append the AuthenticatingAuthority, separated by '!' + * This only works when SSP is used as a gateway. + */ + private $_add_authority = true; + + /** + * Attributes which should be added/appended. + * + * Associative array of arrays. + */ + private $attributes = array(); + + + public function __construct($config, $reserved) { + parent::__construct($config, $reserved); + + assert('is_array($config)'); + + if (array_key_exists('candidates', $config)) { + $this->_candidates = $config['candidates']; + if (!is_array($this->_candidates)) { + throw new Exception('SmartID authproc configuration error: \'candidates\' should be an array.'); + } + } + + if (array_key_exists('id_attribute', $config)) { + $this->_id_attribute = $config['id_attribute']; + if (!is_string($this->_id_attribute)) { + throw new Exception('SmartID authproc configuration error: \'id_attribute\' should be a string.'); + } + } + + if (array_key_exists('add_authority', $config)) { + $this->_add_authority = $config['add_authority']; + if (!is_bool($this->_add_authority)) { + throw new Exception('SmartID authproc configuration error: \'add_authority\' should be a boolean.'); + } + } + + } + + private function addID($attributes, $request) { + foreach ($this->_candidates as $idCandidate) { + if (isset($attributes[$idCandidate][0])) { + if(($this->_add_authority) && (isset($request['saml:AuthenticatingAuthority'][0]))) { + return $idCandidate.':'.$attributes[$idCandidate][0] . '!' . $request['saml:AuthenticatingAuthority'][0]; + } else { + return $idCandidate.':'.$attributes[$idCandidate][0]; + } + } + } + /* + * At this stage no usable id_candidate has been detected. + */ + throw new SimpleSAML_Error_Exception('This service needs at least one of the following + attributes to identity users: '.implode(', ', $this->_candidates).'. Unfortunately not + one of them was detected. Please ask your institution administrator to release one of + them, or try using another identity provider.'); + } + + + /** + * Apply filter to add or replace attributes. + * + * Add or replace existing attributes with the configured values. + * + * @param array &$request The current request + */ + public function process(&$request) { + assert('is_array($request)'); + assert('array_key_exists("Attributes", $request)'); + + $ID = $this->addID($request['Attributes'], $request); + + if(isset($ID)) $request['Attributes'][$this->_id_attribute] = array($ID); + } +}