From 016a6b6c1d0fb9ae37dc5c33ef01a8e7551a6a19 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Mon, 23 Mar 2020 12:13:06 +0100 Subject: [PATCH 3/3] idp_saml2: handle RelayState on posted AuthnRequest (#40722) --- src/authentic2/idp/saml/saml2_endpoints.py | 2 +- src/authentic2/saml/common.py | 3 ++- tests/test_idp_saml2.py | 27 ++++++++++++++++++---- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/authentic2/idp/saml/saml2_endpoints.py b/src/authentic2/idp/saml/saml2_endpoints.py index 71be1e05..fc59f23c 100644 --- a/src/authentic2/idp/saml/saml2_endpoints.py +++ b/src/authentic2/idp/saml/saml2_endpoints.py @@ -430,9 +430,9 @@ def sso(request): consent_answer = request.GET.get('consent_answer', '') if consent_answer: logger.debug(u'back from the consent page for federation with answer %s', consent_answer) - message = get_saml2_request_message(request) server = create_server(request) login = lasso.Login(server) + message = get_saml2_request_message(request, login) # 1. Process the request, separate POST and GET treatment if not message: return HttpResponseForbidden('A SAMLv2 Single Sign On request need a query string', diff --git a/src/authentic2/saml/common.py b/src/authentic2/saml/common.py index 5673d979..7131fe8b 100644 --- a/src/authentic2/saml/common.py +++ b/src/authentic2/saml/common.py @@ -166,13 +166,14 @@ def get_saml2_request_message_async_binding(request): raise Http404('This endpoint is only for asynchornous bindings') -def get_saml2_request_message(request): +def get_saml2_request_message(request, profile): '''Return SAMLv2 message whatever the HTTP binding used''' binding = get_http_binding(request) if binding == 'GET': msg = get_saml2_query_request(request) elif binding == 'POST': msg = get_saml2_post_request(request) + profile.msgRelayState = request.POST.get('RelayState') elif binding == 'SOAP': msg = get_saml2_soap_request(request) else: diff --git a/tests/test_idp_saml2.py b/tests/test_idp_saml2.py index 21e2ea2d..75f32ce3 100644 --- a/tests/test_idp_saml2.py +++ b/tests/test_idp_saml2.py @@ -274,7 +274,7 @@ class SamlSP(object): assert url_parsed.path == reverse('a2-idp-saml-sso'), 'msgUrl should target the sso endpoint' if self.keys: assert 'rsa-sha256' in login.msgUrl - return login.msgUrl, login.msgBody, request.id + return login.msgUrl, login.msgBody, login.msgRelayState, request.id def parse_authn_response(self, saml_response): login = self.login = lasso.Login(self.get_server()) @@ -315,8 +315,14 @@ class Scenario(object): def launch_authn_request(self): # Launch an AuthnRequest - url, body, request_id = self.sp.make_authn_request(**self.make_authn_request_kwargs) - response = self.app.get(url) + url, body, relay_state, request_id = self.sp.make_authn_request(**self.make_authn_request_kwargs) + if body is None: + response = self.app.get(url) + else: # post case + params = {'SAMLRequest': body} + if relay_state is not None: + params['RelayState'] = relay_state + response = self.app.post(url, params=params) utils.assert_redirects_complex( response, @@ -474,7 +480,7 @@ class Scenario(object): utils.assert_xpath_constraints(assertion_xml, constraints, namespaces) -def test_sso_post(app, user): +def test_sso_redirect_post(app, user): scenario = Scenario(app, sp_kwargs=dict(binding='post')) scenario.launch_authn_request() scenario.login(user) @@ -482,7 +488,18 @@ def test_sso_post(app, user): scenario.check_assertion(user=user) -def test_sso_artifact(app, user, keys): +def test_sso_post_post(app, user): + scenario = Scenario( + app, + make_authn_request_kwargs={'method': lasso.HTTP_METHOD_POST}, + sp_kwargs=dict(binding='post')) + scenario.launch_authn_request() + scenario.login(user) + scenario.handle_post_response() + scenario.check_assertion(user=user) + + +def test_sso_redirect_artifact(app, user, keys): scenario = Scenario(app, sp_kwargs=dict(binding='artifact', keys=keys)) scenario.launch_authn_request() scenario.login(user) -- 2.24.0