summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kanakarakis <ivan.kanak@gmail.com>2020-10-28 00:23:48 +0200
committerGitHub <noreply@github.com>2020-10-28 00:23:48 +0200
commit0c22b0f46033189c1a3b761e6846f7ce2634902a (patch)
treec3a30abec5c93e64e7a0eec95b3d7a5282333a87
parent06920df3d7c1ebfdcff92716e798f91f6f9f173c (diff)
parent50b2963d136d1940f9e26bf5d7b1c76cc9df02a2 (diff)
downloadpysaml2-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.rst18
-rw-r--r--src/saml2/client.py5
-rw-r--r--src/saml2/client_base.py1
-rw-r--r--src/saml2/config.py2
-rw-r--r--tests/server_conf.py2
-rw-r--r--tests/test_51_client.py32
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",