Apereo CAS - Bootstrapping Delegated Authentication via REST

Posted by Misagh Moayyed on April 12, 2020 · 5 mins read

Apereo CAS has been able to delegate authentication to external identity providers for quite some time. Simply put, delegation is just a fancy word that means, whether automatically or at the click of a button, the browser is expected to redirect the user to an external identity provider (i.e. Twitter, GitHub, etc) and on the return trip back, CAS is tasked to parse the response and extract attributes, etc to establish an authentication session, issue tickets, etc. In other words, in delegated scenarios, the main identity provider is an external system and CAS simply begins to act as a client or proxy in between.

Registering the existence of such external identity providers is usually and most-commonly done via CAS settings. In this tutorial, we are going to take a look at alternative strategies for bootstrapping a CAS server deployment using an external REST API to feed and register our external identity providers with the CAS application runtime.

Our starting position as follows:

Build

Hop over to the CAS Overlay installation and get CAS built and deployed. Once you have a functional build, remember to include the following extension modules:

implementation "org.apereo.cas:cas-server-support-pac4j-webflow:${project.'cas.version'}"
implementation "org.apereo.cas:cas-server-support-reports:${project.'cas.version'}"

The above two modules begin to activate delegated authentication functionality and reporting features with CAS. We’ll specifically need the latter to take advantage of a few administrative endpoints to monitor the state of our deployment and reload the context as necessary.

Configuration

Next, let’s ensure access to our administrative endpoints:

management.endpoint.reloadContext.enabled=true
management.endpoints.web.exposure.include=reloadContext

cas.monitor.endpoints.endpoint.reloadContext.access=ANONYMOUS

The configuration above allows CAS to enable and have access to the reloadContext actuator endpoint, expose it over the web so we can invoke it using the likes of curl. For the sake of this tutorial, the endpoint is made available without any extra security.

Security Warning!
Production deployments should of course take extra care to ensure all exposed endpoints are protected with adequate security measures.

Next, we need to design a REST API that produces the configuration for our external identity providers. For simplicity, our API is going to respond to GET requests with the following payload:

{
    "callbackUrl": "https://sso.example.org/cas/login",
    "properties": {
        "github.id": "...",
        "github.secret": "..."
    }
}

The structure and syntax of the payload are dictated to CAS by Pac4j and its PropertiesConfigFactory component. The payload should specify the list of identity providers under properties and also indicate a callback URL that is the CAS server itself.

Now that we have the REST API ready, all that is left is to register it with CAS itself:

cas.authn.pac4j.rest.url=https://api.example.org/delegatedauthn

With the above configuration, you should see something close to the below screenshot the very next time you build and run CAS:

image

Refresh & Reload

In addition to GitHub, let’s modify our API payload to also support delegating authentication to an external CAS server:

{
    "callbackUrl": "https://sso.example.org/cas/login",
    "properties": {
        "github.id": "...",
        "github.secret": "...",

        "cas.protocol": "CAS30",
        "cas.loginUrl": "https://external.cas.org/cas/login"
    }
}

Once the change is made, we need to instruct CAS to reload the application context thus invoking our REST API one more time to bootstrap the runtime with the new payload:

curl -X POST -k https://sso.example.org/cas/actuator/reloadContext

Next, refresh the browser page and you should see the newly-registered CAS identity provider listed:

image

Finale

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.

Misagh Moayyed