Apereo CAS - Handling Multiple Logout URLs

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.


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")
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:

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.


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 5.3.0 RC4 Feature Release

...in which I present an overview of CAS 5.3.0 RC4 release.

Apereo CAS - Identity Impersonation

You do not always have to be you. Allow the Apereo CAS server to allow you to pretend to be another person for fun and profit.

Apereo CAS - Customized Settings

Extend the Apereo CAS server to allow custom configuration properties and settings.

Apereo CAS - Access Strategy External URL Redirects

A quick use case walkthrough where the authentication flow in CAS is to be redirected to a customized external URL if service access is denied.

Apereo CAS - Linking Accounts with Delegated Authentication

A quick use case walkthrough where profiles provided by external identity providers to CAS need to be looked up by an identifier in internal databases before CAS can successfully establish an authenticated subject.

Nominate awesome fits for the Apereo board

Provoking thoughts about who might serve well on Apereo board.

Apereo CAS - Test-Driving 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.

Feedback on draft Apereo strategy

Focus on revenue to achieve sustainability. Defer everything else.

Apereo CAS Best [Mal]Practice - Supercharged Overlays

An overview of how a CAS overlay prepped for deployment can tap into internal components, altering logic and behavior for good and evil...but mostly evil.

CAS 5.3.0 RC3 Feature Release

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