diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/smartattributes/docs/smartattributes.txt | 68 | ||||
-rw-r--r-- | modules/smartattributes/lib/Auth/Process/SmartID.php | 105 |
2 files changed, 173 insertions, 0 deletions
diff --git a/modules/smartattributes/docs/smartattributes.txt b/modules/smartattributes/docs/smartattributes.txt new file mode 100644 index 0000000..fbee41c --- /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 0000000..2520bf8 --- /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); + } +} |