diff options
author | Ivan Kanakarakis <ivan.kanak@gmail.com> | 2018-12-06 10:08:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-06 10:08:35 +0100 |
commit | f671747aea352c981333f8b47aaf7a7329471297 (patch) | |
tree | 1c1bf23ed33962bb64afd4d9561676a93902261d | |
parent | 65b136e2c822d3b0e08e0b3c1dc121b6c7de646c (diff) | |
parent | 19b21e218f529db7434fb309314e4377c3db3898 (diff) | |
download | pysaml2-f671747aea352c981333f8b47aaf7a7329471297.tar.gz |
Merge pull request #577 from johanlundberg/non_standard_status_code
Handle non standard response error status codes
-rw-r--r-- | src/saml2/response.py | 43 | ||||
-rw-r--r-- | tests/test_51_client.py | 33 |
2 files changed, 55 insertions, 21 deletions
diff --git a/src/saml2/response.py b/src/saml2/response.py index 323e71e6..6d32e313 100644 --- a/src/saml2/response.py +++ b/src/saml2/response.py @@ -354,26 +354,29 @@ class StatusResponse(object): return self._postamble() def status_ok(self): - if self.response.status: - status = self.response.status - logger.info("status: %s", status) - if status.status_code.value != samlp.STATUS_SUCCESS: - logger.info("Not successful operation: %s", status) - if status.status_code.status_code: - excep = STATUSCODE2EXCEPTION[ - status.status_code.status_code.value] - else: - excep = StatusError - if status.status_message: - msg = status.status_message.text - else: - try: - msg = status.status_code.status_code.value - except Exception: - msg = "Unknown error" - raise excep( - "%s from %s" % (msg, status.status_code.value,)) - return True + status = self.response.status + logger.info("status: %s", status) + + if not status or status.status_code.value == samlp.STATUS_SUCCESS: + return True + + err_code = ( + status.status_code.status_code.value + if status.status_code.status_code + else None + ) + err_msg = ( + status.status_message.text + if status.status_message + else err_code or "Unknown error" + ) + err_cls = STATUSCODE2EXCEPTION.get(err_code, StatusError) + + msg = "Unsuccessful operation: {status}\n{msg} from {code}".format( + status=status, msg=err_msg, code=err_code + ) + logger.info(msg) + raise err_cls(msg) def issue_instant_ok(self): """ Check that the response was issued at a reasonable time """ diff --git a/tests/test_51_client.py b/tests/test_51_client.py index 3dad6d9f..a56ef2cf 100644 --- a/tests/test_51_client.py +++ b/tests/test_51_client.py @@ -28,7 +28,7 @@ from saml2.extension.requested_attributes import RequestedAttribute from saml2.authn_context import INTERNETPROTOCOLPASSWORD from saml2.client import Saml2Client from saml2.pack import parse_soap_enveloped_saml -from saml2.response import LogoutResponse, StatusInvalidNameidPolicy +from saml2.response import LogoutResponse, StatusInvalidNameidPolicy, StatusError from saml2.saml import NAMEID_FORMAT_PERSISTENT, EncryptedAssertion, Advice from saml2.saml import NAMEID_FORMAT_TRANSIENT from saml2.saml import NameID @@ -2325,6 +2325,37 @@ class TestClientNonAsciiAva: resp_str, BINDING_HTTP_POST, {"id1": "http://foo.example.com/service"}) + def test_response_error_status_non_standard_status_code(self): + """ Test that the SP client can parse an authentication response + from an IdP that contains an error status.""" + + conf = config.SPConfig() + conf.load_file("server_conf") + client = Saml2Client(conf) + + resp = self.server.create_error_response( + in_response_to="id1", + destination="http://lingon.catalogix.se:8087/", + info=('http://example.com/status/1.0/cancel', None), + ) + + # Cast the response to a string and encode it to mock up the payload + # the SP client is expected to receive via HTTP POST binding. + if six.PY2: + resp_str = encode_fn(str(resp)) + else: + resp_str = encode_fn(bytes(str(resp), 'utf-8')) + + # We do not need the client to verify a signature for this test. + client.want_assertions_signed = False + client.want_response_signed = False + + # Parse the authentication error response + with raises(StatusError): + client.parse_authn_request_response( + resp_str, BINDING_HTTP_POST, + {"id1": "http://foo.example.com/service"}) + def setup_verify_authn_response(self): idp = "urn:mace:example.com:saml:roland:idp" ava = {"givenName": ["Dave"], "sn": ["ConcepciĆ³n"], |