Apereo CAS - Have you been pawned?


Collaborate
The 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.

Have I been pwned is an online service that tracks security breaches and other datalogs on the internet, allowing you to check if your passwords linked to an email have been compromised. This is a very simple method and does not guarantee that your stuff is safe, or will continue to be safe. It does, however, allow you to have an idea of when data linked to your accounts might have been exposed, and whether you changed (or not) your passwords since that point.

A CAS deployment, as an entity that can support username/password credentials, can be integrated with this service such that after the user logs in with a valid password, CAS may check it against the service API and present a page to the user notifying them if their password has been pwned suggesting they should change it, but allow them to continue.

This sort of thing is fairly simple to do in CAS and while there are a variety of ways to tap into the authentication flow, in this post we shall take advantage of the CAS authenticator post-processors supported by a Groovy script. Our starting position is based on the following:

Configuration

First, we are going to teach CAS about the Groovy script that is to contact the relevant APIs and check for a pawned password:

cas.authn.engine.groovyPostProcessor.location=file:/etc/cas/config/GroovyPostProcessor.groovy

Our script itself may look like this:

import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.credential.*
import java.net.*

def run(Object[] args) {
    def builder = args[0]
    def transaction = args[1]
    def logger = args[2]

    def credential = transaction.getPrimaryCredential().get()
    def password = credential.password
    def passwordSha1 = password.digest('SHA-1').toUpperCase()
    
    /*
        Contact the API using the SHA-1 digest of the credential password.
        Parse through the results, check for matches and produce a warning 
        where appropriate.
     */

    if (passwordHasBeenPawned()) {
        builder.addWarning(new DefaultMessageDescriptor("password.pawned"))  
    }
}

def supports(Object[] args) {
    def credential = args[0]
    def logger = args[1]
    credential instanceof UsernamePasswordCredential
}

Of course, the CAS message/language bundle (typically custom_messages.properties file) should also contain the text for the warning code password.pawned:

password.pawned=Your password is commonly used. Go <a href="https://example.org">here</a> to change it.

Note that the script itself is automatically monitored and cached for changes, so feel free to tweak and update as often as needed to test your changes without restarting the CAS server environment.

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

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.