Skip to content

Commit cfb479a

Browse files
committed
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
1 parent e031c45 commit cfb479a

3 files changed

Lines changed: 174 additions & 0 deletions

File tree

docs/simplesamlphp-authproc.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ The following filters are included in the simpleSAMLphp distribution:
148148
- [`saml:NameIDAttribute`](./saml:nameidattribute): Create an attribute based on the NameID we receive from the IdP.
149149
- [`saml:PersistentNameID`](./saml:nameid): Generate persistent NameID from an attribute.
150150
- [`saml:TransientNameID`](./saml:nameid): Generate transient NameID.
151+
- [`smartattributes:SmartID`](./smartattributes:smartattributes): Generate user ID attribute based on several attributes.
151152

152153

153154

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
SmartAttributes module
2+
======================
3+
4+
The SmartAttributes module provides authentication processing filters that add attributes.
5+
The logic in these filters exceeds what is possible with the standard filters such as [`core:AttributeAdd`], [`core:AttributeAlter`], and [`core:AttributeMap`].
6+
7+
8+
9+
`smartattributes:SmartID`
10+
=========================
11+
12+
Filter to add an identifier attribute, based on the first non-empty attribute from a given list of attribute names.
13+
This is usefull when there are multiple SAML IdPs configured, and there is no common identifier among them.
14+
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.
15+
The filter has the following configuration options:
16+
17+
* `candidates`. An array of attributes names to consider as the identifier attribute. Defaults to:
18+
* eduPersonTargetedID
19+
* eduPersonPrincipalName
20+
* openid
21+
* facebook_targetedID
22+
* twitter_targetedID
23+
* windowslive_targetedID
24+
* myspace_targetedID
25+
* linkedin_targetedID
26+
* `id_attribute`. A string to use as the name of the newly added attribute. Defaults to `smart_id`.
27+
* `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`.
28+
29+
The generated identifiers have the form:
30+
31+
`AttributeName:AttributeValue!AuthenticatingAuthority`
32+
33+
For example:
34+
35+
`eduPersonTargetedID:c4bcbe7ca8eac074f65291fd5524caa88f3115c8!https://login.terena.org/idp/saml2/idp/metadata.php`
36+
37+
Examples
38+
--------
39+
40+
Without any configuration:
41+
42+
'authproc' => array(
43+
50 => array(
44+
'class' => 'smartattributes:SmartID'
45+
),
46+
),
47+
48+
49+
This will add an attribute called `smart_id` with this value:
50+
51+
`eduPersonTargetedID:c4bcbe7ca8eac074f65291fd5524caa88f3115c8!https://login.terena.org/idp/saml2/idp/metadata.php`
52+
53+
54+
Custom configuration:
55+
56+
'authproc' => array(
57+
50 => array(
58+
'class' => 'smartattributes:SmartID',
59+
'candidates' => array('eduPersonTargetedID', 'eduPersonPrincipalName'),
60+
'id_attribute' => 'FooUniversityLocalID',
61+
'add_authority' => false
62+
),
63+
),
64+
65+
This will add an attribute called `FooUniversityLocalID` with this value:
66+
67+
`eduPersonTargetedID:c4bcbe7ca8eac074f65291fd5524caa88f3115c8`
68+
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
3+
class sspmod_smartattributes_Auth_Process_SmartID extends SimpleSAML_Auth_ProcessingFilter {
4+
5+
/**
6+
* Which attributes to use as identifiers?
7+
*
8+
* IMPORTANT: If you use the (default) attributemaps (twitter2name, facebook2name,
9+
* etc., be sure to comment out the entries that map xxx_targetedID to
10+
* eduPersonTargetedID, or there will be no way to see its origin any more.
11+
*/
12+
private $_candidates = array(
13+
'eduPersonTargetedID',
14+
'eduPersonPrincipalName',
15+
'openid',
16+
'facebook_targetedID',
17+
'twitter_targetedID',
18+
'windowslive_targetedID',
19+
'myspace_targetedID',
20+
'linkedin_targetedID',
21+
);
22+
23+
/**
24+
* The name of the generated ID attribute.
25+
*/
26+
private $_id_attribute = 'smart_id';
27+
28+
/**
29+
* Whether to append the AuthenticatingAuthority, separated by '!'
30+
* This only works when SSP is used as a gateway.
31+
*/
32+
private $_add_authority = true;
33+
34+
/**
35+
* Attributes which should be added/appended.
36+
*
37+
* Associative array of arrays.
38+
*/
39+
private $attributes = array();
40+
41+
42+
public function __construct($config, $reserved) {
43+
parent::__construct($config, $reserved);
44+
45+
assert('is_array($config)');
46+
47+
if (array_key_exists('candidates', $config)) {
48+
$this->_candidates = $config['candidates'];
49+
if (!is_array($this->_candidates)) {
50+
throw new Exception('SmartID authproc configuration error: \'candidates\' should be an array.');
51+
}
52+
}
53+
54+
if (array_key_exists('id_attribute', $config)) {
55+
$this->_id_attribute = $config['id_attribute'];
56+
if (!is_string($this->_id_attribute)) {
57+
throw new Exception('SmartID authproc configuration error: \'id_attribute\' should be a string.');
58+
}
59+
}
60+
61+
if (array_key_exists('add_authority', $config)) {
62+
$this->_add_authority = $config['add_authority'];
63+
if (!is_bool($this->_add_authority)) {
64+
throw new Exception('SmartID authproc configuration error: \'add_authority\' should be a boolean.');
65+
}
66+
}
67+
68+
}
69+
70+
private function addID($attributes, $request) {
71+
foreach ($this->_candidates as $idCandidate) {
72+
if (isset($attributes[$idCandidate][0])) {
73+
if(($this->_add_authority) && (isset($request['saml:AuthenticatingAuthority'][0]))) {
74+
return $idCandidate.':'.$attributes[$idCandidate][0] . '!' . $request['saml:AuthenticatingAuthority'][0];
75+
} else {
76+
return $idCandidate.':'.$attributes[$idCandidate][0];
77+
}
78+
}
79+
}
80+
/*
81+
* At this stage no usable id_candidate has been detected.
82+
*/
83+
throw new SimpleSAML_Error_Exception('This service needs at least one of the following
84+
attributes to identity users: '.implode(', ', $this->_candidates).'. Unfortunately not
85+
one of them was detected. Please ask your institution administrator to release one of
86+
them, or try using another identity provider.');
87+
}
88+
89+
90+
/**
91+
* Apply filter to add or replace attributes.
92+
*
93+
* Add or replace existing attributes with the configured values.
94+
*
95+
* @param array &$request The current request
96+
*/
97+
public function process(&$request) {
98+
assert('is_array($request)');
99+
assert('array_key_exists("Attributes", $request)');
100+
101+
$ID = $this->addID($request['Attributes'], $request);
102+
103+
if(isset($ID)) $request['Attributes'][$this->_id_attribute] = array($ID);
104+
}
105+
}

0 commit comments

Comments
 (0)