Closed LVMuser closed 4 years ago
Hi, Please do not use py35 if possible, at least py36. Try to configure allow_unsolicited_response in pysaml2 configuration and then let them know
Looking into the logs more I believe djangoSaml2 is posting two requests, i assume the OutstandingQuery is removed from the cache once the first response is recieved and its the second response with the ID which has since been cleared from the OutstandingQueries cache which causes the error. Could this be an issue caused by DjangoSaml2 sending two requests rather than just the one?
DEBUG /usr/local/lib/python3.5/dist-packages/djangosaml2/views.py:99 views: Login process started
DEBUG /usr/local/lib/python3.5/dist-packages/saml2/mdstore.py:623 mdstore: service => {'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST': [{'location': 'https://login.microsoftonline.com/[redacted]/saml2', '__class__': 'urn:oasis:names:tc:SAML:2.0:metadata&SingleSignOnService', 'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'}], 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect': [{'location': 'https://login.microsoftonline.com/[redacted]/saml2', '__class__': 'urn:oasis:names:tc:SAML:2.0:metadata&SingleSignOnService', 'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'}]}
DEBUG /usr/local/lib/python3.5/dist-packages/djangosaml2/views.py:164 views: Trying binding urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect for IDP https://sts.windows.net/[redacted]/
DEBUG /usr/local/lib/python3.5/dist-packages/saml2/mdstore.py:1075 mdstore: service(https://sts.windows.net/[redacted]/, idpsso_descriptor, single_sign_on_service, None)
DEBUG /usr/local/lib/python3.5/dist-packages/saml2/mdstore.py:623 mdstore: service => {'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST': [{'location': 'https://login.microsoftonline.com/[redacted]/saml2', '__class__': 'urn:oasis:names:tc:SAML:2.0:metadata&SingleSignOnService', 'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'}], 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect': [{'location': 'https://login.microsoftonline.com/[redacted]/saml2', '__class__': 'urn:oasis:names:tc:SAML:2.0:metadata&SingleSignOnService', 'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'}]}
WARNING /usr/local/lib/python3.5/dist-packages/saml2/client_base.py:192 client_base: The SAML service provider accepts unsigned SAML Responses and Assertions. This configuration is insecure.
DEBUG /usr/local/lib/python3.5/dist-packages/djangosaml2/views.py:187 views: Redirecting user to the IdP via urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect binding.
DEBUG /usr/local/lib/python3.5/dist-packages/saml2/mdstore.py:1075 mdstore: service(https://sts.windows.net/[redacted]/, idpsso_descriptor, single_sign_on_service, urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect)
DEBUG /usr/local/lib/python3.5/dist-packages/saml2/mdstore.py:623 mdstore: service => [{'location': 'https://login.microsoftonline.com/[redacted]/saml2', '__class__': 'urn:oasis:names:tc:SAML:2.0:metadata&SingleSignOnService', 'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'}]
INFO /usr/local/lib/python3.5/dist-packages/saml2/client.py:111 client: destination to provider: https://login.microsoftonline.com/[redacted]/saml2
INFO /usr/local/lib/python3.5/dist-packages/saml2/entity.py:486 entity: REQUEST: <samlp:AuthnRequest xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://[redacted].net/saml2/acs/" Destination="https://login.microsoftonline.com/[redacted]/saml2" ID="id-ZEV53y7Cx2PoA3Pfe" IssueInstant="2020-07-21T11:04:29Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"><saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://[redacted].net/saml2/metadata/</saml:Issuer></samlp:AuthnRequest>
INFO /usr/local/lib/python3.5/dist-packages/saml2/client.py:120 client: AuthNReq: <samlp:AuthnRequest xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://[redacted].net/saml2/acs/" Destination="https://login.microsoftonline.com/[redacted]/saml2" ID="id-ZEV53y7Cx2PoA3Pfe" IssueInstant="2020-07-21T11:04:29Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"><saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://[redacted].net/saml2/metadata/</saml:Issuer></samlp:AuthnRequest>
INFO /usr/local/lib/python3.5/dist-packages/saml2/entity.py:226 entity: HTTP REDIRECT
DEBUG /usr/local/lib/python3.5/dist-packages/djangosaml2/views.py:250 views: Saving the session_id in the OutstandingQueries cache: id-ZEV53y7Cx2PoA3Pfe
WARNING /usr/local/lib/python3.5/dist-packages/saml2/client_base.py:192 client_base: The SAML service provider accepts unsigned SAML Responses and Assertions. This configuration is insecure.
DEBUG /usr/local/lib/python3.5/dist-packages/saml2/response.py:325 response: xmlstr: <samlp:Response ID="_d4561ed6-9bf6-4c11-af1c-5e3841fc792a" Version="2.0" IssueInstant="2020-07-21T11:04:30.116Z" Destination="https://[redacted].net/saml2/acs/" InResponseTo="id-ZEV53y7Cx2PoA3Pfe" ...</samlp:Response>
DEBUG /usr/local/lib/python3.5/dist-packages/saml2/response.py:325 response: xmlstr: <samlp:Response ID="_d4561ed6-9bf6-4c11-af1c-5e3841fc792a" Version="2.0" IssueInstant="2020-07-21T11:04:30.116Z" Destination="https://[redacted].net/saml2/acs/" InResponseTo="id-ZEV53y7Cx2PoA3Pfe" ...</samlp:Response>
DEBUG /usr/local/lib/python3.5/dist-packages/saml2/response.py:291 response: response: <samlp:Response xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Destination="https://[redacted].net/saml2/acs/" ID="_d4561ed6-9bf6-4c11-af1c-5e3841fc792a" InResponseTo="id-ZEV53y7Cx2PoA3Pfe" ...</samlp:Response>
ERROR /usr/local/lib/python3.5/dist-packages/saml2/response.py:540 response: Unsolicited response id-ZEV53y7Cx2PoA3Pfe not found in {}
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/saml2/entity.py", line 1143, in _parse_response
response = response.loads(xmlstr, False, origxml=xmlstr)
File "/usr/local/lib/python3.5/dist-packages/saml2/response.py", line 520, in loads
self._loads(xmldata, decode, origxml)
File "/usr/local/lib/python3.5/dist-packages/saml2/response.py", line 340, in _loads
**args)
File "/usr/local/lib/python3.5/dist-packages/saml2/sigver.py", line 1650, in correctly_signed_response
raise SignatureError('Signature missing for response')
saml2.sigver.SignatureError: Signature missing for response
ERROR /usr/local/lib/python3.5/dist-packages/saml2/client_base.py:718 client_base: XML parse error: Unsolicited response: id-ZEV53y7Cx2PoA3Pfe
ERROR /usr/local/lib/python3.5/dist-packages/djangosaml2/views.py:319 views: Received SAMLResponse when no request has been made.
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/saml2/entity.py", line 1143, in _parse_response
response = response.loads(xmlstr, False, origxml=xmlstr)
File "/usr/local/lib/python3.5/dist-packages/saml2/response.py", line 520, in loads
self._loads(xmldata, decode, origxml)
File "/usr/local/lib/python3.5/dist-packages/saml2/response.py", line 340, in _loads
**args)
File "/usr/local/lib/python3.5/dist-packages/saml2/sigver.py", line 1650, in correctly_signed_response
raise SignatureError('Signature missing for response')
saml2.sigver.SignatureError: Signature missing for response
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/djangosaml2/views.py", line 296, in post
response = client.parse_authn_request_response(xmlstr, BINDING_HTTP_POST, outstanding_queries)
File "/usr/local/lib/python3.5/dist-packages/saml2/client_base.py", line 711, in parse_authn_request_response
binding, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/saml2/entity.py", line 1153, in _parse_response
response = response.loads(xmlstr, False, origxml=xmlstr)
File "/usr/local/lib/python3.5/dist-packages/saml2/response.py", line 542, in loads
"Unsolicited response: %s" % self.in_response_to)
saml2.response.UnsolicitedResponse: Unsolicited response: id-ZEV53y7Cx2PoA3Pfe
ERROR /usr/local/lib/python3.5/dist-packages/saml2/response.py:540 response: Unsolicited response id-ZEV53y7Cx2PoA3Pfe not found in {}
Hi, Please do not use py35 if possible, at least py36. Try to configure allow_unsolicited_response in pysaml2 configuration and then let them know
Will upgrade py and try, thank you
I see a single authnRequest there, you can even audit for that using samltracer, on firefox or its equivalent for chrome. I read that warning about unsigned response, add authn_response_signed as follows https://github.com/peppelinux/Django-Identity/blob/master/djangosaml2_sp/djangosaml2_sp/djangosaml2_sp/sp_pysaml2_satosa.py#L74
Put saml2.client_base in debug (in settings LOGGING). Just play with it a bit more, then you'll be able to understand what's happening.
I had the same issue with Python 3.7.6.
DEBUG Trying binding urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect for IDP https://sso.****.***/idp/shibboleth
DEBUG Redirecting user to the IdP via urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect binding.
DEBUG Saving the session_id in the OutstandingQueries cache
[pid: 19882|app: 0|req: 23/27] 10.222.90.79 () {58 vars in 1566 bytes} [Wed Jul 22 13:02:24 2020] GET /saml2/login/ => generated 39 bytes in 30 msecs (HTTP/1.1 302) 7 headers in 830 bytes (2 switches on core 0)
DEBUG Login process started
DEBUG Trying binding urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect for IDP https://sso.****.***/idp/shibboleth
DEBUG Redirecting user to the IdP via urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect binding.
DEBUG Saving the session_id in the OutstandingQueries cache
[pid: 19882|app: 0|req: 24/28] 10.222.90.79 () {56 vars in 1542 bytes} [Wed Jul 22 13:02:25 2020] GET /saml2/login/ => generated 39 bytes in 18 msecs (HTTP/1.1 302) 7 headers in 830 bytes (2 switches on core 0)
Unsolicited response id-TEqwj2KhDl88czDDq
NoneType: None
Unsolicited response
XML parse error: Unsolicited response: id-TEqwj2KhDl88czDDq
ERROR Received SAMLResponse when no request has been made.
Traceback (most recent call last):
File "/opt/nld/var/pyenv/lib/python3.7/site-packages/djangosaml2/views.py", line 296, in post
response = client.parse_authn_request_response(xmlstr, BINDING_HTTP_POST, outstanding_queries)
File "/opt/nld/var/pyenv/lib/python3.7/site-packages/saml2/client_base.py", line 711, in parse_authn_request_response
binding, **kwargs)
File "/opt/nld/var/pyenv/lib/python3.7/site-packages/saml2/entity.py", line 1143, in _parse_response
response = response.loads(xmlstr, False, origxml=xmlstr)
File "/opt/nld/var/pyenv/lib/python3.7/site-packages/saml2/response.py", line 542, in loads
"Unsolicited response: %s" % self.in_response_to)
saml2.response.UnsolicitedResponse: Unsolicited response: id-TEqwj2KhDl88czDDq
Setting allow_unsolicited = True
in the SAML_CONFIG
solved it.
Not for me, @rotherfuchs are you dealing with ADFS? I'd investigate in the cache system you're using and in the way these information would be extracted from there.
put a pdb there and follow the stream if you can do that in a debugging environment
The problem is most likely the "SameSite" and HttpOnly cookie restrictions. Basically if you're using the HTTP POST binding, the POST is initiated via JavaScript on the IdP-supplied page which will not include the Django session cookie, thus the outstanding queries being empty because there is no session. You can check that by doing the flow while having the browser's developer tools "network" tab open and then checking the cookies on the /saml2/acs
POST request. You should see your session cookie in there for the "outstanding sessions" logic to work but you most likely won't.
Potential solutions:
1) Set SameSite=None (and the Secure flag since it's required in that case) on the Django session cookie. This might have detrimental security-related side-effects so I wouldn't recommend.
2) Amending the library to use a different, separate session (with SameSite=None) only for the SAML outstanding queries cache, and keep the default Django session untouched (and secure; with default SameSite settings).
3) Allowing unsolicited responses in your SAML config. This might have security implications (which I'm trying to determine at the moment as I am facing the exact same issue).
I close this issue and invite all of you to continue it here: https://github.com/knaperek/djangosaml2/issues/146#issuecomment-666007053
Thanks everyone for the clarifications
Implemented SameSite workaround in v0.30.0
saml2 complains that it cannot find the outstanding query which was saved to cache by djangoSaml2. Is there a configuration option I am missing? Below are relevant log messages:
I altered saml2 error message to print the self.outstanding_queries being searched which turns up empty.
Am I missing some configuration, or is this a bug?
IDP is Microsoft azure I have no access to however is returning a successful login before this error.