diff --git a/src/saml2/client.py b/src/saml2/client.py index d64bd80..ebd744a 100644 --- a/src/saml2/client.py +++ b/src/saml2/client.py @@ -42,7 +42,7 @@ class Saml2Client(Base): """ The basic pySAML2 service provider class """ def prepare_for_authenticate(self, entityid=None, relay_state="", - binding=saml2.BINDING_HTTP_REDIRECT, vorg="", + binding=None, vorg="", nameid_format=None, scoping=None, consent=None, extensions=None, sign=None, @@ -64,20 +64,31 @@ class Saml2Client(Base): :return: session id and AuthnRequest info """ - destination = self._sso_location(entityid, binding) + expected_binding = binding - reqid, req = self.create_authn_request(destination, vorg, scoping, - response_binding, nameid_format, - consent=consent, - extensions=extensions, sign=sign, - **kwargs) - _req_str = "%s" % req + for binding in [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST]: + if expected_binding and binding != expected_binding: + continue - logger.info("AuthNReq: %s" % _req_str) + destination = self._sso_location(entityid, binding) + logger.info("destination to provider: %s" % destination) - info = self.apply_binding(binding, _req_str, destination, relay_state) + reqid, request = self.create_authn_request( + destination, vorg, scoping, response_binding, nameid_format, + consent=consent, + extensions=extensions, sign=sign, + **kwargs) - return reqid, info + _req_str = str(request) + + logger.info("AuthNReq: %s" % _req_str) + + http_info = self.apply_binding(binding, _req_str, destination, + relay_state) + + return reqid, binding, http_info + else: + raise SignonError("No binding available for singon") def global_logout(self, name_id, reason="", expire=None, sign=None): """ More or less a layer of indirection :-/ diff --git a/src/saml2/client_base.py b/src/saml2/client_base.py index de43387..4f6c20c 100644 --- a/src/saml2/client_base.py +++ b/src/saml2/client_base.py @@ -71,6 +71,10 @@ class VerifyError(SAMLError): pass +class SignonError(SAMLError): + pass + + class LogoutError(SAMLError): pass diff --git a/tests/test_51_client.py b/tests/test_51_client.py index a82a278..eebbccf 100644 --- a/tests/test_51_client.py +++ b/tests/test_51_client.py @@ -619,10 +619,11 @@ class TestClientWithDummy(): def test_do_authn(self): binding = BINDING_HTTP_REDIRECT response_binding = BINDING_HTTP_POST - sid, http_args = self.client.prepare_for_authenticate( + sid, auth_binding, http_args = self.client.prepare_for_authenticate( IDP, "http://www.example.com/relay_state", binding=binding, response_binding=response_binding) + assert binding == auth_binding assert isinstance(sid, basestring) assert len(http_args) == 4 assert http_args["headers"][0][0] == "Location" @@ -669,11 +670,13 @@ class TestClientWithDummy(): def test_post_sso(self): binding = BINDING_HTTP_POST response_binding = BINDING_HTTP_POST - sid, http_args = self.client.prepare_for_authenticate( + sid, auth_binding, http_args = self.client.prepare_for_authenticate( "urn:mace:example.com:saml:roland:idp", relay_state="really", binding=binding, response_binding=response_binding) _dic = unpack_form(http_args["data"][3]) + assert binding == auth_binding + req = self.server.parse_authn_request(_dic["SAMLRequest"], binding) resp_args = self.server.response_args(req.message, [response_binding]) assert resp_args["binding"] == response_binding