Apereo CAS - Webflow Decorations

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.


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:


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:


…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://")) {
                new Decoration(title: "decoration.title.secure",
                            description: "decoration.description.secure"))
        } else {
                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.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}}" />

That should do it.


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


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



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 Vulnerability Disclosure

Disclosure of a security issue with the CAS software.

CAS Release Notes Moved

CAS Release Notes are moved to the CAS site.

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.

Apereo CAS - Authentication Handler Resolution

Learn how to resolve and select authentication handlers based on configurable and flexible filtering criteria.