Merge lp:~roadmr/canonical-identity-provider/saml-extra-attribute-substitutions into lp:canonical-identity-provider

Proposed by Daniel Manrique on 2019-01-25
Status: Merged
Approved by: Daniel Manrique on 2019-01-28
Approved revision: 1680
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: lp:~roadmr/canonical-identity-provider/saml-extra-attribute-substitutions
Merge into: lp:canonical-identity-provider
Diff against target: 50 lines (+34/-0)
2 files modified
src/ubuntu_sso_saml/processors.py (+8/-0)
src/ubuntu_sso_saml/tests/test_processors.py (+26/-0)
To merge this branch: bzr merge lp:~roadmr/canonical-identity-provider/saml-extra-attribute-substitutions
Reviewer Review Type Date Requested Status
Maximiliano Bertacchini 2019-01-25 Approve on 2019-01-28
Review via email: mp+362265@code.launchpad.net

Commit message

Add two new substitutions to be used in SAML attribute values.

"displayname" is normally the users' Full Name in SSO.
"email" is the e-mail address.

These enable reporting richer SAML attributes to SPs who can then create nicer-looking
local identities.

Additionally, the existence of the e-mail attribute/substitution might allow
for full compliance with the SAML 8.3 "persistent" policy, though this would
require additional implementation work.

Description of the change

Add two new substitutions to be used in SAML attribute values.

These were requested by Canonical's support group because they need a presentable "full name" to create end-user-visible accounts (and their rationale is that e.g. showing "John Peterson" to a user is fine, but "lordofallthatisunholyandfun" might not be - and the latter is the best we can do currently, since we only support substitutions for "subject" (which is usually the e-mail) and "personname" (which is the username)).

The new substitutions:

"displayname" is the users' Full Name in SSO.
"email" is the e-mail address.

These enable reporting richer SAML attributes to SPs who can then create nicer-looking
local identities.

Additionally, the existence of the e-mail attribute/substitution might allow
for full compliance with the SAML 8.3 "persistent" policy, though this would
require additional implementation work. With a separate substitution for e-mail, we could send a truly persistent identifier as the SAML subject's NameID, like the OpenID; and then, send the e-mail as a custom attribute.

To post a comment you must log in.
Maximiliano Bertacchini (maxiberta) wrote :

Looks good to me. +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/ubuntu_sso_saml/processors.py'
2--- src/ubuntu_sso_saml/processors.py 2019-01-18 17:46:34 +0000
3+++ src/ubuntu_sso_saml/processors.py 2019-01-25 21:10:18 +0000
4@@ -461,4 +461,12 @@
5 request = self._django_request
6 attributes[key] = request.build_absolute_uri(
7 request.user.get_absolute_url())
8+ elif value == '{{displayname}}':
9+ displayname = self._django_request.user.displayname
10+ if displayname:
11+ attributes[key] = displayname
12+ elif value == '{{email}}':
13+ email = self._subject
14+ if email:
15+ attributes[key] = email
16 return attributes
17
18=== modified file 'src/ubuntu_sso_saml/tests/test_processors.py'
19--- src/ubuntu_sso_saml/tests/test_processors.py 2019-01-18 17:46:34 +0000
20+++ src/ubuntu_sso_saml/tests/test_processors.py 2019-01-25 21:10:18 +0000
21@@ -1799,3 +1799,29 @@
22 '{}</saml:AttributeValue></saml:Attribute>'.format(
23 openid_url))
24 self.assertIn(expected, samlresponse)
25+
26+ def test_email_as_attribute(self):
27+ self.setup_saml_sp(attributes=json.dumps({
28+ 'email-from-attrib': '{{email}}',
29+ }))
30+ email = self.setup_saml_emails()
31+
32+ samlresponse = self.do_saml_request()
33+ expected = ('<saml:Attribute Name="email-from-attrib">'
34+ '<saml:AttributeValue>'
35+ '{}</saml:AttributeValue></saml:Attribute>'.format(
36+ email))
37+ self.assertIn(expected, samlresponse)
38+
39+ def test_displayname_as_attribute(self):
40+ self.setup_saml_sp(attributes=json.dumps({
41+ 'fullname': '{{displayname}}',
42+ }))
43+ displayname = self.account.displayname
44+
45+ samlresponse = self.do_saml_request()
46+ expected = ('<saml:Attribute Name="fullname">'
47+ '<saml:AttributeValue>'
48+ '{}</saml:AttributeValue></saml:Attribute>'.format(
49+ displayname))
50+ self.assertIn(expected, samlresponse)