Shibboleth has a long and tortured history with logout as a concept, and nothing's really changed in that regard, but after many conversations, we have provided a very limited form of logout as part of V2.4.0 that supports the basic use case of terminating a client session with the IdP. This is a very difficult feature to explain to a user, and should only be deployed after careful consideration.
Use of this feature in its current form will not result in a user's sessions with most applications being removed. Its sole benefit is that it limits the damage of a user leaving a session alive to the applications he or she already accessed, and enables use of short timeouts on those systems to further mitigate the threat. All of that is subject to the big caveat that the user has to actually do the logout in the first place.
We have implemented this logout feature by supporting the standard SAML 2.0 LogoutRequest/Response profile over both SOAP and front-channel (typically Redirect) bindings. We have supplemented this by supporting an official extension that enables the IdP to do a better job of controlling the user interface in light of the fact that most/all logout requests sent by an SP will not result in a "full" logout. The IdP is better equipped to express this to its user community than the SP is. To wit, Shibboleth SP V2.5.0 and later send this extension in their logout requests by default.
In addition, we support a proprietary capability to invoke a so-called "local" logout on the IdP by accessing, by default, the profile location /idp/profile/Logout. This is not meant for use within a federated deployment, but if you control the various applications, or are using federated applications that offer a very common "logout redirect location" option but not SAML 2.0 logout, you can choose to use this at your own risk in whatever fashion you're willing to support. More on this below.
There are two modes of operation, SAML and Local. In all cases, the IdP does not initiate requests to SPs and will never inform them of a logout event. It only responds to logout requests.
In the SAML case, the profile handler lives at the usual SAML binding endpoints at paths like /idp/profile/SAML2/Redirect/SLO (analagous to the SSO endpoints). It will respond to signed LogoutRequest messages from SPs that it is configured to support (this is controlled in the usual way, see IdPSAML2LogoutRequestProfileConfig). When it receives a request, it follows the SAML profile involved, which means that it tries to locate an active session using the
<NameID> element in the request. This must correspond to an assertion issued to the SP with that subject identifier associated with an active IdP session. If the client presents a session cookie bound to an active IdP session, then this session MUST match the one identified in the LogoutRequest. Assuming a session can be found, it is terminated.
What happens next depends on the presence of the
<aslo:Asynchronous> extension in the request, which is only likely to be seen from newer Shibboleth SP software. If it is absent, then the IdP generates a standard SAML LogoutResponse message to an endpoint in the SP's metadata (or in the case of SOAP just responds to the request over the same connection). The status code in the response will typically be either:
- an error, indicating that the IdP couldn't locate a matching session or some other problem occurred
- success, with a "partial" sub-status code, indicating that the logout was honored, but that the IdP believes there are sessions active with SPs other than the requester
Less typically, the IdP may respond with total success if it believes that the only SP the user accessed as part of the terminated session was with the SP that sent it the request. That would be an edge case and would be the only "true" logout possible.
If, however, the request did contain the
<aslo:Asynchronous> extension, then processing continues with the Local behavior outlined next.
Picking up from the previous section, or upon a direct non-SAML request, the IdP locates an active session based on the client's cookie and terminates it. If there is no client-identified session, but one was passed in from the SAML processing above, then that session is terminated instead.
A user interface template is then rendered for the client. By default this is a JSP template called logout.jsp. You will find that this template is not by default something you can use. Explaining what the user is supposed to do at this point is a highly localized decision and you MUST customize this template accordingly. Other than the usual request/response objects, the template can access a request attribute that will contain the session being terminated if you want to make use of it. The example is a primitive stab at displaying a list of services the user has accessed during their session.
As an alternative, you may customize this profile handler to use a Velocity template instead of a JSP. This is described below and requires some modifications to handler.xml.
You have free reign within your UI template to add additional processing logic if you choose. For example, you could clear additional cookies that are specific to your deployment and outside the knowledge of the IdP. You could add processing that checks for additional parameters to control what to do after the logout completes. In theory you can use this to integrate into a completely different logout flow. We don't care, it's your code, you do what you want with it. Just understand that exposing that sort of behavior to other systems (such as telling them to send you additional parameters) is on you to support and will not be something the IdP knows about or enforces. Like most of the logout puzzle, this is mostly geared toward enterprise systems that you control.
In the Local case, you have the option to use a Velocity macro template instead of a JSP script to render the UI. JSP is much more flexible, but it has one major drawback: the script has to be embedded in the WAR file and typically requires an IdP restart to change. With Velocity, it is possible to place the file outside the WAR file (e.g. in the IdP's conf directory) and change it without a restart.
To do this, you first need to define a VelocityEngine instance that can locate templates in the filesystem. You can do this without much harm (that I can see) to the built-in instance that is defined in internal.xml, at your own risk. To do this, add
", file" to the end of the value in the
resource.loader property, and add some additional properties as follows:
You can adjust these properties as you see fit of course.
If you're paranoid and want to avoid changing the built-in instance, you could define your own, either inside the same file, or by adding a second Spring configuration file.
Once this is done, you will need to customize the
<ProfileHandler> elements for the
SAML2SLO profile handler by adding a pair of XML attributes, as described in the IdPSAML2LogoutRequestProfileConfig topic.
Caveats and Notes
In some sense this entire feature is a caveat. It doesn't do what most people want it to do (true logout) and it doesn't result in outcomes that really conform to what most application owners really want (assuming they even know what they want, which is rare).
But having said that, the behavior of this feature is very precise. It does exactly what it says above, nothing more or less, and either responds to the SP accurately in SAML terms or displays a template that you have complete control over.
A couple of points that are worth highlighting:
Due to a design limitation in this version, the IdP cannot access more than one session at a time for a given subject identifier. This works okay with transient or directed/persistent identifiers, but limits the IdP's ability to terminate all of the sessions associated with an identifier even if that might be useful. Secondly, because of this limitation, the
SessionIndex attribute in SAML is ignored.
Also, it's worth noting that this whole mechanism really assumes you're using the IdP's session mechanism, the PreviousSession login handler for SSO, and are clustering state if you have more than one server. If you're going the stateless route (as defined here for example), you probably can't support SAML logout requests unless the "Asynchronous" extension is used. It won't break, but you'll probably end up with a lot of SAML errors returned to the SP because a session won't be found. With the extension, at least you can force it to clear the user's front-channel session (which is probably in a cookie you control) and do other useful things by customizing the script/template. You may have something very much like this already deployed, so you can either keep it, or switch to something based on this feature if it makes you happier.
"Full" SAML Logout
We have no current plans to deliver a more comprehensive version of this profile handler that does "real" logout by contacting SPs, at least in any time frame that includes the V3.0 release. We can't say anything for sure beyond that time frame.
There remains a community contribution at https://wiki.aai.niif.hu/index.php/ShibIdpSLO that implements more than this handler does. As part of this feature addition to V2.4.0, we have included some API additions that are meant to support better implementation of that extension in the future. Our hope is that the extension should now be possible without modification of the core IdP code and done as a plugin as with many other extensions, but that of course is up to its maintainer to look at. We want to personally thank them for that work, as it was a useful baseline for this work.