Related question: https://stackoverflow.com/questions/47293940/sp-initiated-single-logout-not-working-with-salesforce
I’m implementing single-sign-on service using Salesforce as identity provider. My app is now working well with single login. My goal is to make logout from my app (service provider) initiate log out in the identity provider (salesforce). For this purpose I send SAML2 request to Salesforce, however, I always get “We are unable to log you out.” error. I searched logs of salesforce to find the cause of the error but didn’t find any.
In my app i use django, to generate saml I use pysaml2 lib. This is my code to generate logout request:
req_id, request = saml2_client.create_logout_request( destination,"<entity-id>",name_id=NameID(text=request.user.email, format=NAMEID_FORMAT_TRANSIENT), expire=soon) # request = saml2_client.sign(request) rstate = saml2_client._relay_state(req_id) msg = http_redirect_message(request, destination, rstate) headers = dict(msg['headers']) location = headers['Location'] return HttpResponseRedirect(location)
Generated xml:
<ns0:LogoutRequest Destination="<logout_endpoint>" ID="<id>" IssueInstant="2019-08-21T06:44:29Z" NotOnOrAfter="2019-08- 21T06:49:29Z" Version="2.0" xmlns:ns0="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:ns1="urn:oasis:names:tc:SAML:2.0:assertion"> <ns1:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid- format:entity">https://localhost:8000/saml2_logout/</ns1:Issuer> <ns1:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid- format:transient">username</ns1:NameID> </ns0:LogoutRequest>
I’m not sure if params I pass to create_logout_request are correct, but I couldn’t find any guide on what they have to be, currently entityid value is the url of my salesforce identity provider.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
TL;DR: Don’t use Single Logout (SLO) in SAML. Terminate your app’s local session and that’s it.
Full story:
SLO might work under a number of carefully curated assumptions. In practice there are a number of issues with “single logout”. Top two problems:
- Asynchronous nature of the front-channel flavor of SLO. (Salesforce and virtually all other identity or service providers only implement front-channel SLO). In this flow there’s no guarantee at the protocol level a service provider OR identity provider will fulfill your SLO request and you have no recourse.
- “Ownership” of (what is essentially) a shared authentication context in a multi-SP scenario. This article does a good job of outlining some of these concerns.
These and other reasons are why SLO is rarely used and the recommended option for service providers is to manage their own session only without thinking about the IdP.
As to your specific problem, you need to sign your authentication request AND include SessionIndex. This is required by the SAML spec
4.4.4.1 Usage
The requester MUST authenticate itself to the responder and ensure
message integrity, either by signing the message or using a
binding-specific mechanism.If the requester is a session participant, it MUST include at least
one<SessionIndex>
element in the request. (Note that the session
participant always receives aSessionIndex
attribute in the
<saml:AuthnStatement>
elements that it receives to initiate the
session)
pysaml2’s client.py.do_logout(…) shows the steps involved to generate a signed request with a SessionIndex; your question on github might yield more details. Your app will need to extract and store the value of SessionIndex in your app’s own session when your app’s session is initiated from Salesforce via SAML, then use that when constructing the logout request.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0