Apereo CAS - Authentication Handler Resolution


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

Nobody enjoys restrictions and limitations but when it comes to Apereo CAS and dealing with authentication transactions, there may be a few cases where you would want to limit or choose a select collection of authentication handlers to respond to a request. The selection criteria could be based on the format or syntax of the credential, the requesting application or some other arbitrary rule. In this post, we are going to briefly look at strategies that allow one to narrow down the list of authentication handler candidates from a global set.

Our starting position is based on:

Credential Criteria

Most authentication strategies in CAS are given a predicate to examine the requested credential for eligibility. This predicate is simply a fancy a condition whose outcome determines whether the authentication strategy/handler should proceed to operate on the credential:

...
cas.authn.accept.credentialCriteria=.+@example.org
cas.authn.accept.name=Default
...

In the above example, the credentialCriteria is a regular expression pattern that is tested against the credential identifier. In other words, if an authentication request is submitted to CAS with a credential whose identifier is test@example.org, this Default authentication handler will be selected to validate the credential.

Per Application

Imagine that we have defined the following authentication handlers/schemes in our CAS configuration:

...                  
cas.authn.accept.users=casuser::Mellon
cas.authn.accept.credentialCriteria=.+@example.org
cas.authn.accept.name=Static 

cas.authn.json.location=file:/etc/cas/config/json-authn.json
cas.authn.json.name=JSON
...

When an authentication request is submitted to CAS, both of the above strategies are made available and selected to respond and verify the given credential. However, you may want to ignore the Static strategy and restrict the selection criteria to only have the JSON authentication handler respond in case the authentication request is submitted from an https://app.example.org application:

{
  "@class" : "org.apereo.cas.services.RegexRegisteredService",
  "serviceId" : "https://app.example.org/.+",
  "name" : "ExampleApp",
  "id" : 1,
  "requiredHandlers" : [ "java.util.HashSet", [ "JSON" ] ]
}

Groovy

In more flexible yet programmatic ways, the selection of authentication handlers can also be delegated to a Groovy script. This is the option where you get to have complete control over the selection process and are tasked with designing the script to return the final filtered collection of authentication handlers that should operate on the credential:

cas.authn.core.groovy-authentication-resolution.location=file:/etc/cas/config/AuthenticationSelection.groovy

The AuthenticationSelection.groovy may look like this:

def run(Object[] args) {
    def handlers = args[0]
    def transaction = args[1]
    def servicesManager = args[2]
    def logger = args[3]

    logger.trace("Resolving authentication handlers ${handlers}...") 
    /*
        Return the final Set of AuthenticationHandler
        components from the provided handlers
        back to CAS to try this transaction.
    */
    handlers
}

def supports(Object[] args) {
    def handlers = args[0]
    def transaction = args[1]
    def servicesManager = args[2]
    def logger = args[3]      

    /*
        Determine if the script should be run,
        and whether it can support the given transaction.
    */
    true
}

Bonus

The most extreme option of all is to simply supply your overall strategy for authentication management and override the CAS-provided engine. To do this, you should start by designing your configuration component to include the following bean:

@Bean
public AuthenticationManager casAuthenticationManager() {
    ...
}

You should only take up this option as a last resort, and maybe not even then.

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 know that all other use cases, scenarios, features, and theories certainly are possible as well. Feel free to engage and contribute as best as you can.

Finally, if you benefit from Apereo CAS as free and open-source software, we invite you to join the Apereo Foundation and financially support the project at a capacity that best suits your deployment. If you consider your CAS deployment to be a critical part of the identity and access management ecosystem and care about its long-term success and sustainability, this is a viable option to consider.

Happy Coding,

Misagh Moayyed

Related Posts

CAS 6.3.0 RC1 Feature Release

...in which I present an overview of CAS 6.3.0 RC1 release.

CAS 6.2.0 RC5 Feature Release

...in which I present an overview of CAS 6.2.0 RC5 release.

CAS 6.2.0 RC4 Feature Release

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

CAS 6.2.0 RC3 Feature Release

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

Apereo CAS - Bootiful CAS Client

Easy to use CAS Client

CAS Vulnerability Disclosure

Disclosure of a security issue with the CAS software.

Checking Out Pull Requests Locally

Check out GitHub pull requests as local branches using a simple bash function.

CAS 6.2.0 RC2 Feature Release

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

CAS Vulnerability Disclosure

Disclosure of a security issue with the CAS software.

Apereo CAS - SAML2 Metadata Overrides

Learn how to manage SAML2 service provider registrations in CAS and override metadata artifacts on a per-application basis.