How SAML2 Single Logout Works

First, lets understand the single logout work flow that is initiated by SP
Please note here,  i am using following diagram (This is copied from specification).  Here IDP is referred to SAML2 SSO Identity Provider and SP is referred to SAML2 SSO Service Provider

Profile Overview 



1.  LogoutRequest issued by SP to  IDP


2.  IDP determines authenticated SPs for given user session.  If there are no SPs, other than the SP who sends logout request, the profile proceeds with step 5. 


Otherwise, steps 3 and 4 are repeated for each SP 

3. LogoutRequest issued by IDP to SP


4. SP issues LogoutResponse to IDP


5. IDP issues LogoutResponse to SP who sends logout request


Let see what is in these requests and response messages 


Logout Request


LogoutRequest is extend from RequestAbstractType.  


There are some attributes that must be in the RequestAbstractType element 

1. ID   – An identifier for the request. This must be unique.  Basically a random number. 


2. Version  – Indicate SAML version 


3. IssueInstant – Time instant of issue of the request. The time value is encoded in UTC


Apart from that,  One of following is a required attribute for LogoutRequest request…

4. BaseID or NameID or EncryptedID  


This indicate the principle (user identifier).  Basically name that is known to both IDP and SP. 


Also there are few optional elements


5. NotOnOrAfter  – The time at which the request expires in UTC


6. Reason  –  reason for the logout, in the form of a URI reference.


There are two standard reasons 


urn:oasis:names:tc:SAML:2.0:logout:user  – user terminates session and initiates logout

urn:oasis:names:tc:SAML:2.0:logout:admin – admin terminates session and initiates logout

7. SessionIndex  – This is the session identifier that is used to identify the user session with both IDP and SP for given user.


Logout Repsonse


LogoutRepsonse is extend from StatusResponseType.  There are some attributes that must be in the StatusResponseType element.  i.e.  ID, Version and IssueInstant which is same as in RequestAbstractType. There is element called Status  element that is required.  Status element would contain the status code corresponding to the request. 


Sample Scenario


Lets take sample scenarios to explain how IDP and SPs handle the single logout scenario. Here we assume that there are IDP and two SPs; i.e called as SP1 and SP2 


Please note all request response messages must be signed or otherwise authenticated and integrity protected by the under line protocol. 


Step 1.  User is trying access SP1 and user has no authenticated session, therefore user is redirected to IDP


Step 
2. IDP has no authenticated session for user. Therefore user would be authenticated with user store.    


Step 
3. After successful authentication; 


IDP creates SAML token based on user and user’s attributes.  

IDP creates a session for user and IDP that is normally called as SSO session.  This SSO session is uniquely identified by session Id (which would be sent in assertion as SessionIndex) and the user. SSO session would contain details about the SP1.  Mostly SSO session would be persisted by the IDP

Step 
4. User is redirected to SP1 with SAML Response. 


Here we are interesting in followings element in the SAML Assertion 


a) Subject   –   This is used to identify the authenticated User. Mostly NameID is used for this.  Basically this is user name of the authenticated user. 

<saml2:nameid>admin</saml2:nameid>

b) AuthnStatement  –  This provides some statement describing how subject has been authenticated with IDP. 

<saml2:authnstatement authninstant="2013-06-28T11:49:29.879Z" sessionindex="26C0530CBEA1DCF404C95B029D6A64AF">
<saml2:authncontext>
<saml2:authncontextclassref>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:authncontextclassref>
</saml2:authncontext>
</saml2:authnstatement>

 Here user has been authenticated by providing password.  Also it specifies the session identifier of the session that has been created with IDP and user, using SessionIndex attribute 

Step 5. If SAML response is valid, SP1 would create session for user and SP1.  Then, created session would be map with the received SessionIndex value.


Step 6. Now same user is trying to access SP2. 
and user has no authenticated session, therefore user is redirected to IDP

Step 7. IDP has an authenticated SSO session for user and IDP. Therefore SAML token is created.  SSO session would be updated with SP2 details. 


Step 8. User is redirected to SP2 with SAML Response.   SAML Assertion would be same as 
we discussed in step4

Step 9. If SAML response is valid, SP2 would create session with user and SP2.  Then, created session would be map with the received SessionIndex.


Now lets see single logout scenario….


Step 10. User is trying to logout from SP1. Then LogoutRequest is sent to IDP from SP1.  


Lets see what should be in this request. 


Basically,  SP1 need to provided the SSO session that is associated with IDP and the User. 


SP1 could finds out, received SessionIndex id and NameID for the user. As these details has been kept in SP’s  session


Then creates LogoutRequest based on that.. 


Sample LogoutRequest would be as follows

<saml2p:logoutrequest id="flkjhgfehcfjkjjmabgkcmlcnalbcillibfeeeag" issueinstant="2013-06-28T11:51:06.024Z" notonorafter="2013-06-28T11:56:06.024Z" reason="urn:oasis:names:tc:SAML:2.0:logout:user" version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2:nameid format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">admin</saml2:nameid>
<saml2p:sessionindex>26C0530CBEA1DCF404C95B029D6A64AF</saml2p:sessionindex>
</saml2p:logoutrequest>

Step 11. IDP validates LogoutRequest and If valid, it finds out the associate SSO session for given SessionIndex and that also is matched with NameID 

Step 12. IDP identifies the SPs that have been authenticated for the user from the SSO session.   Then IDP sends LogoutRequest to each SP (other than SP1) with corresponding SessionIndex and NameID


Therefore same LogoutRequest that is discussed in step10 would be sent to SP2 from IDP


Step 13. SP2 validates and processes LogoutRequest. SP2 invalidates the session that is associated with SessionIndex and is matched with NameID 

Step 14. SP2 sends LogoutResponse  to IDP with the status of success

<saml2p:status>
<saml2p:statuscode value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</saml2p:status>

Step 15. IDP validates the LogoutResponse  and tracks on received status

Step 
16. Finally IDP invalidates SSO session  that is  associated with SessionIndex and 
is matched with NameID 

Step 
17. IDP sends  LogoutResponse to SP1  


If all are success 
LogoutResponse would be with status code   

urn:oasis:names:tc:SAML:2.0:status:Success

If SP2 sends an error status in LogoutResponse, then with status code

urn:oasis:names:tc:SAML:2.0:status:PartialLogout

If any other error, it would be with error status code.

However, Step12, Step13, Step 14 and Step15  are normally happening in separate threads.  It means once, IDP receives a logout request from SP1,  IDP would invalidate the SSO session that is  associated with SessionIndex and is matched with NameID.  Then IDP sends the LogoutResponse to SP1.  But in separate flow IDP would execute the Step12, Step13, Step 14 and Step15  steps.

I guess,  this would help you to understand how single logout must be implemented. Basically , if i simplify, this in code level…

In IDP implementation, There must be a some kind of SSO session (session between User and IDP) persistence method. It can be a simple in-memory Map;  with SessionIndex (session Id) as the key and session as the value of the Map. Please find sample implementation from here     

In SP implementation. There must be a some kind of user session (session between User and SP) persistence method. It can be a simple in-memory Map; 
with SessionIndex (received SessionIndex in Assertion) as the key and user session as the value of the Map. Please find sample implementation from here    

With WSO2 Identity Server  release, you could find sample web apps that demonstrate single logout functions. Please refer this