Apereo CAS - Webflow Decorations


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

There are times where you may need to modify the CAS login webflow to include additional pieces of data, typically fetched from outside resources and endpoints. Examples include displaying announcements on the CAS login screen or calling a REST API to fetch today’s Cafeteria menu, etc. While the webflow itself can certainly be extended in many fancy ways, one easy option is to let CAS decorate the login webflow automatically by reaching out outside sources to fetch data while taking care of the internal webflow configuration and injections on its own. Of course, once data is fetched and made available to CAS you still have the responsibility of using that data to properly display it in the appropriate view and style it correctly…and that’s what we are going to do here!

Our use case is such:

  • Examine the incoming application URL that has submitted a login request to CAS.
  • If it’s an https URL, display a message on the screen to reassure the user of their security and safety.
  • If it’s NOT an https URL, display a message on the screen anyway to frighten and notify the user!

Our starting position is based on:

Configuration

Imagine we have the following service definition registered with CAS:

{
  "@class": "org.apereo.cas.services.RegexRegisteredService",
  "serviceId": "^https://.*",
  "name": "HTTPS and IMAPS",
  "id": 10000001,
  "description": "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
}

The serviceId field above indicates that all URLs starting with https:// are recognized by our CAS server. Later on, we may relax this pattern to allow http-based URLs as well so as to allow our logic for URL detection and follow-up messages on the screen.

Next, we are going to teach CAS about the location of a script that would handle the execution of our use case and conditions:

cas.webflow.login-decorator.groovy.location=file:/path/to/GroovWebflowDecorator.groovy

…of course, our Groovy script would be:

import java.util.*
import java.io.*
import org.apereo.cas.web.support.*

def run(Object[] args) {
    def requestContext = args[0]
    def applicationContext = args[1]
    def logger = args[2]

    def service = WebUtils.getService(requestContext)
    logger.info("Decorating the login view for ${service}")
    if (service != null) {
        if (service.id.startsWith("https://")) {
            requestContext.flowScope.put("decoration", 
                new Decoration(title: "decoration.title.secure",
                            description: "decoration.description.secure"))
        } else {
            requestContext.flowScope.put("decoration", 
                new Decoration(title: "decoration.title.insecure",
                            description: "decoration.description.insecure"))
        }
    }
}

class Decoration implements Serializable {
    private static final long serialVersionUID = 8517547235465666978L
    String title
    String description
}

The above script simply attempts to stuff a Decoration object into the webflow using the lookup key decoration. Our object carries two fields for title and description that point to keys in our language bundles. The webflow will be decorated based on the incoming service and our condition therein, exposing access to our data object under the key decoration, which can then be used in CAS views to display data, etc.

Mainly, etc.

Groovy Script
The script is cached and watched for changes. As you adjust the logic and update the script, CAS may detect changes to the file and auto-refresh its cached version of it after a small delay.

Of course, the CAS message/language bundle (typically custom_messages.properties file) should also contain the text for our message keys/codes as well:

decoration.title.secure=Secured!
decoration.title.insecure=Insecure!

decoration.description.secure=This application runs behind https.
decoration.description.insecure=This application runs behind http!

At this point, the webflow is properly decorated with the data we need to display. All we have to do is find a relevant CAS view and display that data, perhaps in serviceui.html somewhere:

<div th:if="${decoration}">
    <h3 th:utext="#{${decoration.title}}" />
    <p th:utext="#{${decoration.description}}" />
</div>

That should do it.

Test

If you attempt to access CAS using an application that does in fact run behind https, the following picture is what you should expect:

image

Next, if you relax the serviceId requirement to allow for http applications as well, you might see the following outcome:

image

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.

Happy Coding,

Misagh Moayyed

Related Posts

CAS 6.1.0 RC5 Feature Release

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

Apereo CAS - Are We Logged In Yet?

Learn how to modify and extend a CAS deployment to determine whether an SSO session is still valid and tied to a user authentication session.

Apereo CAS - REST API Integrations

Learn how to integrate with CAS using its REST API to authenticate, exchange tickets and get access to user profiles and attributes.

CAS 6.1.0 RC4 Feature Release

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

Apereo CAS - Multifactor Provider Selection

Learn how to configure CAS to integrate with and use multiple multifactor providers at the same time. This post also reveals a few super secret and yet open-source strategies one may use to select appropriate providers for authentication attempts, whether automatically or based on a menu.

Apereo CAS - Dockerized Hazelcast Deployments

Learn how to run CAS backed by a Hazelcast cluster in Docker containers and take advantage of the Hazelcast management center to monitor and observer cluster members.

Apereo CAS - Configuration Security w/ Jasypt

Learn how to secure CAS configuration settings and properties with Jasypt.

CAS 6.1.0 RC3 Feature Release

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

Apereo CAS - SAML2 Metadata Query Protocol

Learn how you may configure Apereo CAS to fetch and validate SAML2 metadata for service providers from InCommon's MDQ server using the metadata query protocol.

Saving Time is Time Consuming

May you live in the best of times. May you live in the startup times.