From cfb479a222a0c5cb1d8cd2fe05a62cdc93b00945 Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Mon, 1 Oct 2012 10:23:46 +0000 Subject: [PATCH] New filter: smartattributes:SmartID Thanks to Dick Visser for implementing it! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3180 44740490-163a-0410-bde0-09ae8108e29a --- docs/simplesamlphp-authproc.txt | 1 + .../smartattributes/docs/smartattributes.txt | 68 ++++++++++++ .../lib/Auth/Process/SmartID.php | 105 ++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 modules/smartattributes/docs/smartattributes.txt create mode 100644 modules/smartattributes/lib/Auth/Process/SmartID.php diff --git a/docs/simplesamlphp-authproc.txt b/docs/simplesamlphp-authproc.txt index 7b3b08d9d..da1500f01 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 000000000..fbee41c6f --- /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 000000000..2520bf828 --- /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); + } +} -- GitLab