Apereo CAS - Handling Multiple Logout URLs


Collaborate
This blog is managed and hosted on GitHub. If you wish to update the contents of this post or if you have found an inaccuracy and wish to make corrections, we recommend that you please submit a pull request to this repository.

Overview

CAS has had support for single logout for quite a while. This feature basically means that CAS is able to invalidate client application sessions in addition to its own SSO session, assuming client applications are ready to honor and accept logout requests with special configuration. When a CAS session ends, it notifies each of the services that the SSO session is no longer valid, and that relying parties need to invalidate their own session by processing a special logout request. Remember that the callback submitted to each CAS-protected application is simply a notification; nothing more. It is the responsibility of the application to intercept that notification and properly destroy the user authentication session, either manually, via a specific endpoint or more commonly via a CAS client library that supports SLO.

By default, applications are contacted by CAS using their original URL to receive the logout notification; which is simply the purified service URL used when an authentication request on behalf of the application is submitted to CAS. This tutorial focuses on ways one can customize the logout URL in more dynamic ways.

This tutorial deals with:

Single Logout URL

In dealing with single logout operations, the URL endpoint to receive the logout notification can be customized on a per-application basis:

{
  "@class" : "org.apereo.cas.services.RegexRegisteredService",
  "serviceId" : "https://\\w+.example.org",
  "name" : "Our Example Domain",
  "id" : 1,
  "description" : "The example domain provides examples in examplish ways",
  "logoutUrl" : "https://logout.example.org"
}

This is, of course, the simplest option and means that if CAS has established sessions with one or more applications that qualify for the above definition, those applications will receive logout notifications at the specified URL above when the logout engine in CAS begins to process records.

Many Logout URLs

One should note that the logoutUrl above not only static but also singular. With configuration only, there is not a way for one to specify more than one URL in cases where that might be needed. While the service configuration above presents a rather simplified version of the feature, CAS itself provides the internal mechanics to recognize and handle a collection of logout URLs for a given application. Our task here would be to extend the configuration slightly to implement this scenario and inject the behavior into the runtime.

We can start by preparing CAS with a customized configuration component that would house our customizations for this use case. Once that is done, take note of the following bean definition posted in CasCoreLogoutConfiguration.java today:

@ConditionalOnMissingBean(name = "singleLogoutServiceLogoutUrlBuilder")
@Bean
public SingleLogoutServiceLogoutUrlBuilder singleLogoutServiceLogoutUrlBuilder() {
    return new DefaultSingleLogoutServiceLogoutUrlBuilder(this.urlValidator);
}

Note how the bean is marked as conditional, meaning it will only be used by CAS if an alternative definition by the same is not found. So, in order for CAS to pick up our own alternative implementation, we are going to provide that bean definition in our own configuration class as such:

@Bean
public SingleLogoutServiceLogoutUrlBuilder singleLogoutServiceLogoutUrlBuilder() {
    return new CustomSingleLogoutServiceLogoutUrlBuilder(this.urlValidator);
}
Compile Dependencies
Note that in order for the CAS overlay build to compile our changes and put them to good use, the overlay must be prepared with the required module used during the compilation phase. Otherwise, there will be errors complaining about missing symbols, etc.

Now, it’s time to actually design our very own CustomSingleLogoutServiceLogoutUrlBuilder. Here is a modest example:

public class CustomSingleLogoutServiceLogoutUrlBuilder extends DefaultSingleLogoutServiceLogoutUrlBuilder {

    ...
    public Collection<URL> determineLogoutUrl(RegisteredService registeredService, WebApplicationService service) {

        /*
            Stuff happens to determine the collection of the logout URLs
            given the provided service and its registered definition in the registry.
        */
    }

}

That should do it. The very next time you build and deploy the changes, CAS should pick up our own bean definition and accompanying implementation class. It should be obvious that inside the class above, you have options to calculate the logout URLs as you wish since the builder object is expected to return a collection of URLs. To fully make this behavior dynamic, you may want to invest time researching service custom properties and externalize the logout function with special tags designed as properties that would then be consumed and processed in the above component.

So…

I hope this review was of some help to you and I am sure that both this post as well as the functionality it attempts to explain can be improved in any number of ways. Please feel free to engage and contribute as best as you can.

Happy Coding,

Misagh Moayyed

Related Posts

CAS 6.1.0 RC3 Feature Release

...in which I present an overview of CAS 6.1.0 RC3 release.

Apereo CAS 6.1.x - Credential Caching & Proxy AuthN

Learn how you may configure Apereo CAS to capture and cache the credential's password and the proxy-granting ticket in proxy authentication scenarios, pass them along to applications as regular attributes/claims. We will also be reviewing a handful of attribute release strategies that specifically affect authentication attributes, conveying metadata about the authentication event itself.

Apereo CAS 6.1.x - Attribute Repositories w/ Person Directory

An overview of CAS attribute repositories and strategies on how to fetch attributes from a variety of sources in addition to the authentication source, merge and combine attributes from said sources to ultimately release them to applications with a fair bit of caching.

Apereo CAS 6.1.x - Building CAS Feature Modules

An overview of how various CAS features modules today can be changed and tested from the perspective of a CAS contributor working on the codebase itself to handle a feature request, bug fix, etc.

CAS 6.1.0 RC2 Feature Release

...in which I present an overview of CAS 6.1.0 RC2 release.

Apereo CAS - Riffing on Attribute Release Policies

Learn how to release the kraken of attributes to CAS clients, relying parties and service providers using a variety of attribute release policies and authentication protocols, sampled and collected here to fun and profit.

Apereo CAS - Delegated Authentication to SAML2 Identity Providers

Learn how your Apereo CAS deployment may be configured to delegate authentication to an external SAML2 identity provider.

Apereo CAS - Custom Login Fields w/ Dynamic Bindings

Learn how to extend the Spring Webflow model to add custom fields to the CAS login form and the authentication process and take advantage of the additional user-provided data in customized authentication handlers.

Apereo CAS as an OAuth2 Authorization Server

Learn how to configure CAS as an OAuth2 Authorization Server and configure Spring Boot client app to work with it

Apereo CAS - SAML2 Identity Provider Integration w/ Gitlab (also staring HAProxy and LDAP)

Learn how Apereo CAS may act as a SAML2 identity provider for Gitlab and run everything locally on a workstation with Docker and Java.