Extending CAS Webflow

The objective of this guide is to better describe how CAS utilizes Spring Webflow to accommodate various authentication flows. Please remember that this is NOT to teach one how Spring Webflow itself works internally. If you want to learn more about Spring Webflow and understand the internals of actions, states, decisions and scopes please see this guide.

CAS by default operates on the following core webflow configuration files:

Flow Description
login Authentication flow for login attempts.
logout Authentication flow for logout attempts.

The above flows present a minimal structure for what CAS needs at its core to handle login and logout flows. It is important to note that at runtime many other actions and states are injected into either of these flows dynamically depending on the CAS configuration and presence of feature modules. Also note that each feature module itself may dynamically present other opinionated subflow configuration files that are automagically picked up at runtime.

Modifying Webflow

In modest trivial cases, you may be able to overlay and modify the core flow configuration files to add or override the desired behavior. Again, think very carefully before introducing those changes into your deployment environment. Avoid making ad-hoc changes to the webflow as much as possible and consider how the change you have in mind might be more suitable as a direct contribution to the CAS project itself so you can just take advantage of its configuration and NOT its maintenance.

To learn how to introduce new actions and state into a Spring Webflow, please see this guide.

Speak Up

If you find something that is broken where the webflow auto-configuration strategy fails to deliver as advertised, discuss that with the project community and submit a patch that corrects the bug or adds the desired behavior as a modest enhancement. Avoid one-off changes and make the change where the change belongs.

In more advanced cases where you may need to take a deep dive and alter core CAS behavior conditionally, you would need to take advantage of the CAS APIs to deliver changes. Using the CAS APIs directly does present the following advantages at some cost:

  • Changes are all scoped to Java (Groovy, Kotlin, Clojure, etc).
  • You have the full power of Java to dynamically and conditionally augment the Spring Webflow.
  • Your changes are all self-contained.
  • Changes are now part of the CAS APIs and they will be compiled. Breaking changes on upgrades, if any, should be noticed immediately at build time.

Java

This is the most traditional yet most powerful method of dynamically altering the webflow internals. You will be asked to write components that auto-configure the webflow and inject themselves into the running CAS application context only to be executed at runtime.

At a minimum, your overlay will need to include the following modules:

1
2
3
4
5
<dependency>
  <groupId>org.apereo.cas</groupId>
  <artifactId>cas-server-core-webflow</artifactId>
  <version>${cas.version}</version>
</dependency>
1
implementation "org.apereo.cas:cas-server-core-webflow:${project.'cas.version'}"
1
2
3
4
5
6
7
8
9
dependencyManagement {
  imports {
    mavenBom "org.apereo.cas:cas-server-support-bom:${project.'cas.version'}"
  }
}

dependencies {  
  implementation "org.apereo.cas:cas-server-core-webflow"
}

Design

Design your dynamic webflow configuration agent that alters the webflow using the following form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SomethingWebflowConfigurer extends AbstractCasWebflowConfigurer {
     public SomethingWebflowConfigurer(FlowBuilderServices flowBuilderServices,
                                       FlowDefinitionRegistry flowDefinitionRegistry,
                                       ApplicationContext applicationContext,
                                       CasConfigurationProperties casProperties) {
        super(flowBuilderServices, flowDefinitionRegistry, applicationContext, casProperties);
     }

    @Override
    protected void doInitialize() throws Exception {
        var flow = super.getLoginFlow();
        // Magic happens; Call 'super' to see 
        // what you have access to and alter the flow.
    }
}

Register

You will then need to register your newly-designed component into the CAS application runtime:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package org.example.something;

@Configuration("somethingConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class SomethingConfiguration implements CasWebflowExecutionPlanConfigurer {

    @Autowired
    private CasConfigurationProperties casProperties;

    @Autowired
    @Qualifier("loginFlowRegistry")
    private FlowDefinitionRegistry loginFlowDefinitionRegistry;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private FlowBuilderServices flowBuilderServices;

    @ConditionalOnMissingBean(name = "somethingWebflowConfigurer")
    @Bean
    public CasWebflowConfigurer somethingWebflowConfigurer() {
        return new SomethingWebflowConfigurer(flowBuilderServices,
            loginFlowDefinitionRegistry, applicationContext, casProperties);
    }

    @Override
    public void configureWebflowExecutionPlan(final CasWebflowExecutionPlan plan) {
        plan.registerWebflowConfigurer(somethingWebflowConfigurer());
    }
}

Configuration classes need to be registered with CAS inside a src/main/resources/META-INF/spring.factories file:

1
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.example.something.SomethingConfiguration
To Build & Beyond

Note that compiling configuration classes and any other piece of Java code that is put into the CAS Overlay may require additional CAS modules and dependencies on the classpath. You will need to study the CAS codebase and find the correct modules that contain the components you need, such as CasWebflowConfigurer and others.

See this guide for more info.

Groovy

You may configure CAS to alter and auto-configure the webflow via a Groovy script. This is the less elaborate option where you have modest access to CAS APIs that allow you alter the webflow. However, configuration and scaffolding of the overlay and required dependencies is easier as all is provided by CAS at runtime.

The following settings and properties are available from the CAS configuration catalog:

The configuration settings listed below are tagged as Required in the CAS configuration metadata. This flag indicates that the presence of the setting may be needed to activate or affect the behavior of the CAS feature and generally should be reviewed, possibly owned and adjusted. If the setting is assigned a default value, you do not need to strictly put the setting in your copy of the configuration, but should review it nonetheless to make sure it matches your deployment expectations.

  • cas.webflow.groovy.location=
  • The location of the resource. Resources can be URLS, or files found either on the classpath or outside somewhere in the file system.

    org.apereo.cas.configuration.model.core.web.flow.GroovyWebflowProperties.

    The configuration settings listed below are tagged as Optional in the CAS configuration metadata. This flag indicates that the presence of the setting is not immediately necessary in the end-user CAS configuration, because a default value is assigned or the activation of the feature is not conditionally controlled by the setting value.