SAML-Toolkits / python3-saml

MIT License
682 stars 304 forks source link

Signature validation failed. SAML Response rejected #282

Open danielniccoli opened 2 years ago

danielniccoli commented 2 years ago

Hi,

I use the flask demo and cannot get the signature validation to work.

As far as I know the place to put the IdP Certificate is in the settings-json under idp/x509cert.

I tried to set x509cert to the Base64-encoded certificate string (one-liner) as well as to a file path to the base64-encoded certificate itself. Restarted the demo-server every time. I still get the same error every time.

I left it blank, too, in hope to just omit the validation. But still the same error.

{
    "strict": true,
    "debug": true,
    "sp": {
        "x509cert": "",
        "privateKey": ""
    },
    "idp": {

        "x509cert": ""
    }
}
pitbulk commented 2 years ago

I left it blank, too, in hope to just omit the validation. But still the same error.

Signature validation is always required, otherwise, anyone could craft it own SAMLResponse and access your system.

I tried to set x509cert to the Base64-encoded certificate string (one-liner) as well as to a file path to the base64-encoded certificate itself. Restarted the demo-server every time. I still get the same error every time.

Maybe you are registering the wrong x509cert. Makes sure the value you provide to the settings matches the public cert used by the IdP. You could use a browser extension named SAML Tracer (firefox | chrome) in order to record the SAML flow and later inspect it. Check the Signature value.. and check the value of X509Certificate that is the one that must be registereed on php-saml settings.

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
    <ds:Reference URI="#pfxf59f04cc-4f19-fc42-ff60-5a84a3069dde">
    <ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms>
    <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
    <ds:DigestValue>EDztjf+gPbmOUDaPdqc1thxhah4=</ds:DigestValue></ds:Reference>
  </ds:SignedInfo>
  <ds:SignatureValue>xxxSignaturexxxx</ds:SignatureValue>
  <ds:KeyInfo>
      <ds:X509Data><ds:X509Certificate>xxxxIdPxxPublicxxCertxxx</ds:X509Certificate></ds:X509Data>
  </ds:KeyInfo>
</ds:Signature>
gardarh commented 2 years ago

I'm hitting a similar issue against Azure AD with logout (slo) requests. I'm using HTTP GET to process the SLO.

I'm using python3.10 and version 1.14.0 of python3-saml. I am successfully validating saml login requests with the same cert.

Ultimately utils.validate_binary_sign() is returning False but what is being sent to dsig_ctx.verify_binary() looks legit (the signed payload looks like it is formatted according to spec and when I decode the binary signature and urlencode it, it is exactly what I got from the query string).

This is my code (I'm using django):

        saml_config_dict = django_utils.generate_saml_config(client)
        saml_request_object = prepare_saml_request_object(request)
        saml_auth = onelogin_saml2.OneLogin_Saml2_Auth(
            saml_request_object, old_settings=saml_config_dict
        )
        saml_auth.process_slo()
        if len(saml_auth.get_errors()) > 0:
            errors = ", ".join(saml_auth.get_errors())
            print(f"SLO failed, error: {errors}")

Which prints out "SLO failed, error: invalid_logout_response_signature, Signature validation failed. Logout Response rejected"

My saml_request_object is:

{
'https': 'off',
'http_host': 'localhost:8080',
'script_name': '/api/v1/sso/logout-from-idp/',
'get_data': <QueryDict: {
'SAMLResponse': ['fZJBa9wwEIX/itFdlla21pbwGkJTysI2gW7IoZcwtkaJwSsZj9w0/fV1veQQKDmOZt6b90lqCC7jZE/xOS7pB9IUA2F2vD2wp8K5rtey5l6aPS/7neOgteFOdrUzrvZ13bHsEWcaYjgwlUuWHYkWPAZKENJ6JJXiq0EhH2Rld8qWKq9r85Nlt0hpCJA25UtKE1kh4M8yIyeKHN0z5hO8QYDxLQ095QMJmAbxayfWvhi3uNzP8cIHN4l1cXgP/xAP7P7u6+n+2/HuSRqttO69K8CoUhm/EmBVVlVRAbh9J0tTo1d7lv2+jIHsdhsHtszBRqCBbIALkk29Pd98P9mV0U5zTLGPI2ubjXa+Sj8XARHO/2hZ+05LifLXIbj4SnnAJNBpqHznuJaoeAlec+OV57KoKuWdckbXohHXnW1zfbdzgrTQx+pLdJg9wrjg55lom7bnpe+RiIm2ER9Nxf/+RvsX'],
'RelayState': ['https://*redacted*/api/v1/rest-auth/logout/'],
'Signature': ['AzuOHsUAq/0T0nfzAXENyX17C4JCd4gKkvwEmLOdbbnCgVLaaId1Z00VkTGVA+gR5yH5jbBPT9T6JCCk35TwQlMsD46qbwhTYwf7pV4705BwLkfTA0gwYsiPC2WlN2Nb+xFJV96OMSFEZdv5mOQX0r1CtYpZRV9vwCp+DA7XYKtjLdkF9q+KoibkeSjOUBR2nfDpCd3PxXLGu/ZLYtpt186LgwL7PX6CKIbNeKRz3gJ4Z1Lcv02WvF1riFdtAZOizuS9jwVFFcP2pDBDxpdXssNMruNa9mxRjg4j29vNKc3tc2x58rx4GfwS7GOZk+rlVsqjCS5L290JZvmizJxYpQ=='],
'SigAlg': ['http://www.w3.org/2001/04/xmldsig-more#rsa-sha256']
}>,
'post_data': <QueryDict: {}>, 'server_port': 8080
}

And my saml_config_dict is:

{'debug': False,
 'idp': {'certFingerprint': '',
         'certFingerprintAlgorithm': 'sha1',
         'entityId': 'https://sts.windows.net/ed5a7fbd-50e2-4af5-9f2f-03772fd2d958/',
         'singleLogoutService': {'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
                                 'url': 'https://login.microsoftonline.com/ed5a7fbd-50e2-4af5-9f2f-03772fd2d958/saml2'},
         'singleSignOnService': {'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
                                 'url': 'https://login.microsoftonline.com/ed5a7fbd-50e2-4af5-9f2f-03772fd2d958/saml2'},
         'x509cert': '-----BEGIN CERTIFICATE-----\n'
                     'MIIC8DCCAdigAwIBAgIQGKzmgsp5PoVJDvN6LkJz9DANBgkqhkiG9w0BAQsFADA0\n'
                     'MTIwMAYDVQQDEylNaWNyb3NvZnQgQXp1cmUgRmVkZXJhdGVkIFNTTyBDZXJ0aWZp\n'
                     'Y2F0ZTAeFw0yMjA2MTcxMzU5NTBaFw0yNTA2MTcxMzU5NTBaMDQxMjAwBgNVBAMT\n'
                     'KU1pY3Jvc29mdCBBenVyZSBGZWRlcmF0ZWQgU1NPIENlcnRpZmljYXRlMIIBIjAN\n'
                     'BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx+4SBAmWmGEvSwyevRS4SqNO8gDo\n'
                     '/mE8UjrcM+wXNlDxNLHbuTqFqyaoanoLXvqZwrwjfpdpR9mB3EXdv3rio7jZNteA\n'
                     'gbouoC+dbwNF89na4Y3Jx3cdMGvA+JQhRoXHgvwp3IKqCYv4PkOQMe7NepdUSIkb\n'
                     'XorkRFOs4JQQTdj5shDo/+sQvJJIiZ9obgc43xyWYAhauNumlM2fwMBDgw1ZZvD1\n'
                     '55MMT20rh7wNURXQGmP9qzZClqdybImu+2AEmfdO85kKm+QVxZqQ3y0YFFkPELvF\n'
                     'P3X++ZZOSl8Dv6Rf6kqRPImoTOrbFWv//MldzAJw5BSZUpn4JQlJ/MFqLQIDAQAB\n'
                     'MA0GCSqGSIb3DQEBCwUAA4IBAQC10pmV/ddMF/G8mxZ2KLziqMSclZezjIjAJbs0\n'
                     'EJcvBU5qii+hqs/t7rJuoERDzKiJeoDZgqX+anvDH7wmB7kODUyQyfXK1uern97G\n'
                     'V9+31Xm5zq1HIdjzfz4H5HMBSsMt919u/hwYbsWQjSrMmnLI61c9+wX//GCorv9Z\n'
                     'vbKrjn/38J/twSFna7F5+uF2a06ANG3IyYCCSbSSV+MO2Y/rCPbiFpyXYHelarMG\n'
                     'nLCsLA3tJmDNWcyoMOimANDwZc3+e4jW/pvIILvSUuASMk3dtMt80qfoLqfc4gJf\n'
                     'rlq8i8Qe4d4luRJLVSDKa7SARqhMj22lsjNOk7vOy6Bjgq5W\n'
                     '-----END CERTIFICATE-----\n'},
 'security': {'allowRepeatAttributeName': False,
              'authnRequestsSigned': False,
              'digestAlgorithm': 'http://www.w3.org/2001/04/xmlenc#sha256',
              'failOnAuthnContextMismatch': False,
              'logoutRequestSigned': False,
              'logoutResponseSigned': False,
              'metadataCacheDuration': None,
              'metadataValidUntil': None,
              'nameIdEncrypted': False,
              'rejectDeprecatedAlgorithm': False,
              'requestedAuthnContext': True,
              'requestedAuthnContextComparison': 'exact',
              'signMetadata': False,
              'signatureAlgorithm': 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
              'wantAssertionsEncrypted': False,
              'wantAssertionsSigned': False,
              'wantAttributeStatement': False,
              'wantMessagesSigned': False,
              'wantNameId': True,
              'wantNameIdEncrypted': False},
 'sp': {'NameIDFormat': 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
        'assertionConsumerService': {'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
                                     'url': 'http://localhost:8080/api/v1/sso/login/'},
        'attributeConsumingService': {},
        'entityId': 'https://localhost/sso/sp/',
        'privateKey': '',
        'singleLogoutService': {'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
                                'url': 'http://localhost:8080/api/v1/rest-auth/logout/'},
        'x509cert': ''},
 'strict': True}

Is there anything obviously wrong with my setup? Could anyone verify that the SLO works against Azure AD with a similar configuration?

pitbulk commented 1 year ago

Is possible that more than 1 certificate is registered at AzureAD and during the SLO a different x509cert/private key pair was used than the one registered?

Also try to play with the setting: lowercase_urlencoding

ghazi-git commented 10 months ago

ran into the same issue as gardarh today: logout request with a django web app, using MS Entra ID (previously Azure AD). Setting lowercase_urlencoding=True fixed the issue.

Thank you @pitbulk