diff options
author | Ivan Kanakarakis <ivan.kanak@gmail.com> | 2020-10-28 00:23:48 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-28 00:23:48 +0200 |
commit | 0c22b0f46033189c1a3b761e6846f7ce2634902a (patch) | |
tree | c3a30abec5c93e64e7a0eec95b3d7a5282333a87 | |
parent | 06920df3d7c1ebfdcff92716e798f91f6f9f173c (diff) | |
parent | 50b2963d136d1940f9e26bf5d7b1c76cc9df02a2 (diff) | |
download | pysaml2-0c22b0f46033189c1a3b761e6846f7ce2634902a.tar.gz |
Merge pull request #734 from Worteks/sign-logout-response
Add logout_responses_signed configuration option to sign logout responses
-rw-r--r-- | docs/howto/config.rst | 18 | ||||
-rw-r--r-- | src/saml2/client.py | 5 | ||||
-rw-r--r-- | src/saml2/client_base.py | 1 | ||||
-rw-r--r-- | src/saml2/config.py | 2 | ||||
-rw-r--r-- | tests/server_conf.py | 2 | ||||
-rw-r--r-- | tests/test_51_client.py | 32 |
6 files changed, 58 insertions, 2 deletions
diff --git a/docs/howto/config.rst b/docs/howto/config.rst index 060f4f68..e1c2025f 100644 --- a/docs/howto/config.rst +++ b/docs/howto/config.rst @@ -987,6 +987,24 @@ Example:: } } +logout_responses_signed +""""""""""""""""""""""" + +Indicates if this entity will sign the Logout Responses while processing +a Logout Request. + +This can be overridden by application code when calling ``handle_logout_request``. + +Valid values are True or False. Default value is False. + +Example:: + + "service": { + "sp": { + "logout_responses_signed": False, + } + } + subject_data """""""""""" diff --git a/src/saml2/client.py b/src/saml2/client.py index 60b108ef..11c737c1 100644 --- a/src/saml2/client.py +++ b/src/saml2/client.py @@ -487,7 +487,7 @@ class Saml2Client(Base): else: raise SAMLError("Unsupported binding") - def handle_logout_request(self, request, name_id, binding, sign=False, + def handle_logout_request(self, request, name_id, binding, sign=None, sign_alg=None, relay_state=""): """ Deal with a LogoutRequest @@ -534,6 +534,9 @@ class Saml2Client(Base): response_bindings = self.config.preferred_binding[ "single_logout_service"] + if sign is None: + sign = self.logout_responses_signed + response = self.create_logout_response(_req.message, response_bindings, status, sign, sign_alg=sign_alg) rinfo = self.response_args(_req.message, response_bindings) diff --git a/src/saml2/client_base.py b/src/saml2/client_base.py index 51a3a574..5a70d885 100644 --- a/src/saml2/client_base.py +++ b/src/saml2/client_base.py @@ -162,6 +162,7 @@ class Base(Entity): attribute_defaults = { "logout_requests_signed": False, + "logout_responses_signed": False, "allow_unsolicited": False, "authn_requests_signed": False, "want_assertions_signed": False, diff --git a/src/saml2/config.py b/src/saml2/config.py index eb00c7cf..2f6e13b0 100644 --- a/src/saml2/config.py +++ b/src/saml2/config.py @@ -95,6 +95,7 @@ SP_ARGS = [ "name_id_policy_format", "name_id_format_allow_create", "logout_requests_signed", + "logout_responses_signed", "requested_attribute_name_format", "hide_assertion_consumer_service", "force_authn", @@ -201,6 +202,7 @@ class Config(object): self.virtual_organization = None self.only_use_keys_in_metadata = True self.logout_requests_signed = None + self.logout_responses_signed = None self.disable_ssl_certificate_validation = None self.context = "" self.attribute_converters = None diff --git a/tests/server_conf.py b/tests/server_conf.py index 2b87b942..f1dc33d6 100644 --- a/tests/server_conf.py +++ b/tests/server_conf.py @@ -14,6 +14,8 @@ CONFIG = { "required_attributes": ["surName", "givenName", "mail"], "optional_attributes": ["title"], "idp": ["urn:mace:example.com:saml:roland:idp"], + "logout_responses_signed": True, + "logout_requests_signed": True, "requested_attributes": [ { "name": "urn:oid:1.3.6.1.4.1.5923.1.1.1.2", diff --git a/tests/test_51_client.py b/tests/test_51_client.py index 2b71146c..c1d52531 100644 --- a/tests/test_51_client.py +++ b/tests/test_51_client.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- from base64 import encodebytes as b64encode +from base64 import decodebytes as b64decode import uuid import six from six.moves.urllib import parse @@ -51,7 +52,6 @@ AUTHN = { "authn_auth": "http://www.example.com/login" } - def generate_cert(): sn = uuid.uuid4().urn cert_info = { @@ -413,6 +413,36 @@ class TestClient: except Exception: # missing certificate self.client.sec.verify_signature(ar_str, node_name=class_name(ar)) + def test_logout_response(self): + req_id, req = self.server.create_logout_request( + "http://localhost:8088/slo", "urn:mace:example.com:saml:roland:sp", + name_id=nid, reason="Tired", expire=in_a_while(minutes=15), + session_indexes=["_foo"]) + + info = self.client.apply_binding( + BINDING_HTTP_REDIRECT, req, destination="", + relay_state="relay2") + loc = info["headers"][0][1] + qs = parse.parse_qs(loc[1:]) + samlreq = qs['SAMLRequest'][0] + resphttp = self.client.handle_logout_request(samlreq, nid, + BINDING_HTTP_REDIRECT) + _dic = unpack_form(resphttp['data'], "SAMLResponse") + xml = b64decode(_dic['SAMLResponse'].encode('UTF-8')) + + # Signature found + assert xml.decode('UTF-8').find(r"Signature") > 0 + + # Try again with logout_responses_signed=False + self.client.logout_responses_signed = False + resphttp = self.client.handle_logout_request(samlreq, nid, + BINDING_HTTP_REDIRECT) + _dic = unpack_form(resphttp['data'], "SAMLResponse") + xml = b64decode(_dic['SAMLResponse'].encode('UTF-8')) + + # Signature not found + assert xml.decode('UTF-8').find(r"Signature") < 0 + def test_create_logout_request(self): req_id, req = self.client.create_logout_request( "http://localhost:8088/slo", "urn:mace:example.com:saml:roland:idp", |