SAML-Toolkits / python3-saml

MIT License
672 stars 302 forks source link

Is there a workaround for HTTP-POST binding for SLO? #205

Open CR1AT0RS opened 3 years ago

CR1AT0RS commented 3 years ago

First I wanna thank you for making this library very well structured and easy to use.

Question: My IDP Okta's logout SLO supports HTTP-POST binding so I can't logout the user. Is there a workaround for Okta SLO and use it with the HTTP-POST binding?

My SP: Django IDP: Okta

"idp": { "entityId": "http://example.com/kbiebrwerwrw", "singleSignOnService": { "url": "https://test.okta.com/app/rtest/example/sso/saml", "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" }, "singleLogoutService": { "url": "https://test.okta.com/app/testingwx_1/whew8389hrhui4/slo/saml", "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" },

Screen Shot 2020-07-28 at 3 38 36 PM
ljudva commented 3 years ago

Hello,

I'll shamelessly jump in, if Octa supports only POST, than this is the question for Octa...

The idP should support both. So just like https://github.com/onelogin/python3-saml/issues/204 nothing to do with this lib...

CR1AT0RS commented 3 years ago

Thanks for jumping in but I am gonna have to disagree. Also it's spelled "Okta" with a "K". The question is:

pitbulk commented 3 years ago

Hi @CR1AT0RS

"Is there a plan to support HTTP_POST on SLO"?

No

204 - JumpCloud not supporting SLO is an issue on Idp Side. This issue is about library's implementation of SLO on SP side.

This library implements the basic (LITE), and SLO HTTP-Redirect binding is the one required on SP LITE.

A library for SSO can be agnostic of the vendor so just because OneLogin uses HTTP_REDIRECT that doesn't mean everyone has to do the same. HTTP_POST is also a bit harder to implement than HTTP_REDIRECT but there are advantages and disadvantages to both approaches.

Disagree, the library is agnostic and is compatible with SAML IdPs that follows SAML standard.

Based on the definition of the Conformance SAML spec Page 9:

Single Logout (SP-initiated) HTTP redirect and Single Logout (IdP-initiated) HTTP redirect are a MUST on IdP, IDP Lite, SP and SP Lite.  No requirement is specified for POST/Artifact bindings on SLO for SP Lite.

Also the saml2int profile specifies:

[SDP-SP25]
The HTTP-Redirect binding  MUST be used for the transmission of <samlp:LogoutRequest> messages.

[SDP-SP26]
SPs MUST support the HTTP-Redirect binding for the receipt of <samlp:LogoutRequest> messages, in the event that inbound <samlp:LogoutRequest> messages are supported.

And defines the requirement of support HTTP-POST only for samlp:Response:

[SDP-SP08]
SPs MUST support the HTTP-POST binding for the receipt of <samlp:Response> messages. Support for other bindings is OPTIONAL.

Not sure why Okta decided to not support HTTP-Redirect binding on SLO. Have you asked them?

spaceone commented 3 years ago

I would like to see support for the HTTP-POST binding as well.

rajeshyogeshwar commented 3 years ago

Although it's been made clear that there is no plan to support HTTP-POST binding for logout, is there a way one can implement it by himself/herself while still using this library? Is there a way where in one can use classes/methods from this library and implement it?

pitbulk commented 3 years ago

@rajeshyogeshwar Yes, it is possible to add HTTP-POST binding support to the library.

In all the following scenarios, when you generate the SAML Message, you will need to send it via POST instead of Redirect and sign the XML and include the signature embed, if the sign flag is enabled, I will describe the complex scenario, but take in mind the add_sign is optional.

If you are looking for being able to send AuthNRequest supporting HTTP-POST then you need to extend the Auth class adding a new login method that will initialize the object with no signature, retrieving it with get_request and then embed the Signature on the XML using the add_sign. Check this

In order to be able to send LogoutRequest using HTTP-POST you will need to make a similar process than the previously mentioned, but adding a new logout method that will get a LogoutRequest class, get the request and sign it.

In order to be able to send LogoutRequest using HTTP-POST you will need to extend the processSLO method and get the LogoutResponse and sign it.

If you also want to support LogoutRequest and LogoutResponse to be received via POST, you will need to extend the processSLO in order to be able to read SAML Message on GET parameters and also verify the Signature element if it is included inside the XML.

As you see, supporting HTTP-POST binding is doable, if I decide to support it I will need to support all the previous scenarios described, and that introduces extra complexity to the toolkit as you can see. My goal is to keep the toolkit simple so I'm not adding it for now.

Ideally, I could add its support as an addon so only in specific cases dev could add it when they need it, but I didn't found the time to implement this. Take in mind that SAML toolkits are supported not only for Python, but for PHP, Ruby and Java where I should implement its support as well, so the effort isn't trivial.

rajeshyogeshwar commented 3 years ago

@pitbulk I absolutely appreciate your response and I do understand that a good amount of effort is required for it to be done, hence I am not saying it had to be there in the library. But if others knew a way for it to be done by themselves, it definitely takes away the need for constant demand for the support. I hope you understand what I mean here. Thank you for quick response and guidance. I will take my time to try it out and see if I can get it functional.

kfveerachitturi commented 2 years ago

Do we know if AuthNRequest is supporting HTTP-POST in the latest java library version?

matumot commented 2 years ago

In django's example, https://github.com/onelogin/python3-saml/blob/master/demo-django/demo/views.py I added patch in front of index function shown below, and found it works for HTTP-POST binding for SLO, although I think this is not good idea. I checked this with keycloak 18.0.1.


def index(request):

req = prepare_django_request(request)
auth = init_saml_auth(req)

errors = []
error_reason = None
not_auth_warn = False
success_slo = False
attributes = False
paint_logout = False

# patch by matumot -->                                                                                                          
if req["post_data"].get("SAMLResponse") and req["post_data"].get("RelayState"):
    req['get_data']['SAMLResponse'] = req["post_data"].get("SAMLResponse")
# <---