Merge lp:~ricardokirkner/canonical-identity-provider/saml-no-clobber-issuer into lp:canonical-identity-provider/release

Proposed by Ricardo Kirkner
Status: Merged
Approved by: Ricardo Kirkner
Approved revision: no longer in the source branch.
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: lp:~ricardokirkner/canonical-identity-provider/saml-no-clobber-issuer
Merge into: lp:canonical-identity-provider/release
Diff against target: 138 lines (+50/-9)
3 files modified
src/ubuntu_sso_saml/processors.py (+2/-2)
src/ubuntu_sso_saml/tests/test_processors.py (+47/-6)
src/ubuntu_sso_saml/utils.py (+1/-1)
To merge this branch: bzr merge lp:~ricardokirkner/canonical-identity-provider/saml-no-clobber-issuer
Reviewer Review Type Date Requested Status
Daniel Manrique (community) Approve
Review via email: mp+342891@code.launchpad.net

Commit message

keep AuthnRequest Issuer in REQUEST_ISSUER to avoid clobbering system-wide ISSUER value

saml2idp keeps the system-wide issuer (which is used when rendering the saml response) in the ISSUER key; storing the AuthnRequest issuer in that key was breaking saml responses (as they'd report as being issued by the SP instead of the IdP).

To post a comment you must log in.
Revision history for this message
Daniel Manrique (roadmr) wrote :

Oops... looks OK to put this in a different dict key.

Thanks!

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 2018-04-06 19:41:49 +0000
3+++ src/ubuntu_sso_saml/processors.py 2018-04-09 19:02:02 +0000
4@@ -328,7 +328,7 @@
5 if issuer is not None:
6 issuer = issuer.text
7 params['ACS_URL'] = acs_url
8- params['ISSUER'] = issuer
9+ params['REQUEST_ISSUER'] = issuer
10 params['REQUEST_ID'] = request['id']
11 params['DESTINATION'] = request.get('destination', '')
12 params['PROVIDER_NAME'] = request.get('providername', '')
13@@ -371,7 +371,7 @@
14
15 def _validate_sp_config(self):
16 acs_url = self._request_params.get('ACS_URL')
17- issuer = self._request_params.get('ISSUER')
18+ issuer = self._request_params.get('REQUEST_ISSUER')
19 sp_config = get_config_from_processor(self)
20 if sp_config is not None:
21 return sp_config
22
23=== modified file 'src/ubuntu_sso_saml/tests/test_processors.py'
24--- src/ubuntu_sso_saml/tests/test_processors.py 2018-04-06 19:41:49 +0000
25+++ src/ubuntu_sso_saml/tests/test_processors.py 2018-04-09 19:02:02 +0000
26@@ -134,7 +134,7 @@
27
28 def setup_saml_sp(self, **kwargs):
29 acs_url = kwargs.pop('acs_url', self.ACS_URL)
30- issuer = kwargs.pop('issuer', getattr(self, 'ISSUER', None))
31+ issuer = kwargs.pop('issuer', getattr(self, 'REQUEST_ISSUER', None))
32 prefer_canonical_email = kwargs.get('prefer_canonical_email', False)
33 twofactor_required = kwargs.pop('twofactor_required', False)
34 allowed_teams = kwargs.pop('allowed_teams', '')
35@@ -1167,7 +1167,7 @@
36
37 """) # noqa
38 ACS_URL = 'https://saml.example.com/saml_acs_url'
39- ISSUER = 'https://saml.example.com/metadata'
40+ REQUEST_ISSUER = 'https://saml.example.com/metadata'
41 AUDIENCE = 'https://login.ubuntu.com/+saml'
42 RELAY_STATE = 'https://example.com/'
43 # Note REQUEST_DATA is incomplete and needs a SAMLRequest added by
44@@ -1202,7 +1202,7 @@
45 data = dict(**self.REQUEST_DATA)
46 payload = self.SAML_PAYLOAD.format(
47 audience=self.AUDIENCE, acs_url=self.ACS_URL,
48- issuer=self.ISSUER, relay_state=self.RELAY_STATE)
49+ issuer=self.REQUEST_ISSUER, relay_state=self.RELAY_STATE)
50 if compressed:
51 data['SAMLRequest'] = codex.deflate_and_base64_encode(payload)
52 else:
53@@ -1285,7 +1285,7 @@
54
55 data = self.get_request_data()
56 payload = SAML_PAYLOAD.format(
57- audience=self.AUDIENCE, issuer=self.ISSUER)
58+ audience=self.AUDIENCE, issuer=self.REQUEST_ISSUER)
59 # override data with ACS_URL-less payload
60 data['SAMLRequest'] = base64.b64encode(payload)
61
62@@ -1322,7 +1322,7 @@
63
64 data = self.get_request_data()
65 payload = SAML_PAYLOAD.format(
66- audience=self.AUDIENCE, issuer=self.ISSUER)
67+ audience=self.AUDIENCE, issuer=self.REQUEST_ISSUER)
68 # override data with ACS_URL-less payload
69 data['SAMLRequest'] = base64.b64encode(payload)
70
71@@ -1359,7 +1359,7 @@
72
73 data = self.get_request_data()
74 payload = SAML_PAYLOAD.format(
75- audience=self.AUDIENCE, issuer=self.ISSUER)
76+ audience=self.AUDIENCE, issuer=self.REQUEST_ISSUER)
77 # override data with ACS_URL-less payload
78 data['SAMLRequest'] = base64.b64encode(payload)
79
80@@ -1375,6 +1375,47 @@
81 assert len(forms) == 1
82 self.assertEqual(forms[0].get('action'), self.ACS_URL)
83
84+ def test_response_with_system_issuer_not_authnrequest_issuer(self):
85+ self.setup_saml_sp()
86+
87+ SAML_PAYLOAD = ("""
88+<?xml version="1.0" encoding="UTF-8"?>
89+<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
90+ ID="THE_ID"
91+ Version="2.0"
92+ IssueInstant="2016-09-08T21:40:15.988Z"
93+ ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
94+ Destination="{audience}"
95+ >
96+ <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">{issuer}</saml:Issuer>
97+ <samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
98+ Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
99+ AllowCreate="true"
100+ />
101+ <samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
102+ Comparison="exact"
103+ >
104+ <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
105+ </samlp:RequestedAuthnContext>
106+</samlp:AuthnRequest>
107+
108+
109+""") # noqa
110+
111+ data = self.get_request_data()
112+ payload = SAML_PAYLOAD.format(
113+ audience=self.AUDIENCE, issuer=self.REQUEST_ISSUER)
114+ # override data with ACS_URL-less payload
115+ data['SAMLRequest'] = base64.b64encode(payload)
116+
117+ samlresponse = self.do_saml_request(data=data)
118+ self.assertNotIn(
119+ 'https://saml.example.com/metadata</saml:Issuer>', samlresponse)
120+ self.assertIn(
121+ '{}</saml:Issuer>'.format(
122+ saml2idp_metadata.SAML2IDP_CONFIG['issuer']),
123+ samlresponse)
124+
125 def test_enabled_db_spconfig_overrides_settings(self):
126 # make sure there is an "old/custom" processor handling this request
127 self.ACS_URL = google_apps.GOOGLE_APPS_ACS
128
129=== modified file 'src/ubuntu_sso_saml/utils.py'
130--- src/ubuntu_sso_saml/utils.py 2018-04-06 19:41:49 +0000
131+++ src/ubuntu_sso_saml/utils.py 2018-04-09 19:02:02 +0000
132@@ -29,7 +29,7 @@
133
134 def get_config_from_processor(proc):
135 acs_url = proc._request_params.get('ACS_URL')
136- issuer = proc._request_params.get('ISSUER')
137+ issuer = proc._request_params.get('REQUEST_ISSUER')
138 return get_config_for_acs(acs_url, issuer=issuer)
139
140