From 6ec4b67beb28806067c98f71b008e383ebd8fa07 Mon Sep 17 00:00:00 2001 From: Kelvin Chan Date: Tue, 17 Dec 2019 15:06:53 -0500 Subject: [PATCH 1/2] SAML bug fixes * Fix error casting request_xml to bytes when request_xml is an object --- djangosaml2/views.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/djangosaml2/views.py b/djangosaml2/views.py index cb812295..49789d93 100644 --- a/djangosaml2/views.py +++ b/djangosaml2/views.py @@ -37,6 +37,7 @@ UnsolicitedResponse) from saml2.s_utils import UnsupportedBinding from saml2.sigver import MissingKey +from saml2.samlp import AuthnRequest from saml2.validate import ResponseLifetimeExceed, ToEarly from saml2.xmldsig import ( # support for SHA1 is required by spec SIG_RSA_SHA1, SIG_RSA_SHA256) @@ -205,6 +206,9 @@ def login(request, binding=binding, **kwargs) try: + if isinstance(request_xml, AuthnRequest): + # request_xml will be an instance of AuthnRequest if the message is not signed + request_xml = str(request_xml) saml_request = base64.b64encode(bytes(request_xml, 'UTF-8')).decode('utf-8') http_response = render(request, post_binding_form_template, { From c27f208374fee95210e1ced743a4c4490f8745d8 Mon Sep 17 00:00:00 2001 From: Kelvin Chan Date: Wed, 29 Apr 2020 09:21:03 -0400 Subject: [PATCH 2/2] Add test for unsigned post authentication request --- djangosaml2/tests/conf.py | 3 +- .../tests/remote_metadata_post_binding.xml | 33 +++++++++++++++++++ djangosaml2/tests/utils.py | 16 +++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 djangosaml2/tests/remote_metadata_post_binding.xml create mode 100644 djangosaml2/tests/utils.py diff --git a/djangosaml2/tests/conf.py b/djangosaml2/tests/conf.py index 2c1bd92e..5f829cc2 100644 --- a/djangosaml2/tests/conf.py +++ b/djangosaml2/tests/conf.py @@ -19,7 +19,7 @@ def create_conf(sp_host='sp.example.com', idp_hosts=['idp.example.com'], - metadata_file='remote_metadata.xml'): + metadata_file='remote_metadata.xml', authn_requests_signed=True): try: from saml2.sigver import get_xmlsec_binary @@ -55,6 +55,7 @@ def create_conf(sp_host='sp.example.com', idp_hosts=['idp.example.com'], 'optional_attributes': ['eduPersonAffiliation'], 'idp': {}, # this is filled later 'want_response_signed': False, + 'authn_requests_signed': authn_requests_signed, }, }, diff --git a/djangosaml2/tests/remote_metadata_post_binding.xml b/djangosaml2/tests/remote_metadata_post_binding.xml new file mode 100644 index 00000000..941f9580 --- /dev/null +++ b/djangosaml2/tests/remote_metadata_post_binding.xml @@ -0,0 +1,33 @@ + + + + + + + + MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo + + + + + + + MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + Lorenzo's test IdP + idp.example.com IdP + http://idp.example.com/ + + + Administrator + lgs@yaco.es + + + diff --git a/djangosaml2/tests/utils.py b/djangosaml2/tests/utils.py new file mode 100644 index 00000000..58331ca4 --- /dev/null +++ b/djangosaml2/tests/utils.py @@ -0,0 +1,16 @@ +from html.parser import HTMLParser + + +class SAMLPostFormParser(HTMLParser): + """ + Parses the SAML Post binding form page for the SAMLRequest value. + """ + + saml_request_value = None + + def handle_starttag(self, tag, attrs): + attrs_dict = dict(attrs) + + if tag != "input" or attrs_dict.get("name") != "SAMLRequest": + return + self.saml_request_value = attrs_dict.get("value")