This recipe takes you from nothing to a working CAS server on your own machine: run it, configure it, register an
application and log in. It is meant for learning and evaluation; Getting Started explains how
to plan a real deployment.
Settings Are Links
Click any setting on this page, such as cas.server.name, to see its description,
default value, module and other formats right here, without leaving the page. Press ShiftShift
anywhere in the documentation to search all settings.
1. Try It With Docker
If you only want to see CAS running, start the official image. Set CAS_VERSION to a CAS release listed on
Docker Hub, such as 8.0.2; step 2 builds your overlay from the same
release:
1
2
3
4
export CAS_VERSION=8.0.2
docker run --rm-p 8080:8080 \-eSERVER_SSL_ENABLED=false-eSERVER_PORT=8080 \"apereo/cas:${CAS_VERSION}"
Open http://localhost:8080/cas/login and log in as casuser with the password Mellon. The two variables
are server.ssl.enabled and server.port written as environment variables;
every setting can be passed this way. See Docker Installation for more.
The Docker image is a standalone preview. The remaining steps build your own overlay with the features you choose.
Stop the preview with Ctrl+C before starting your overlay on the same port.
2. Create an Overlay
A real deployment is built from a WAR overlay: a small Gradle project that pulls in CAS and holds only what you add or
change. Choose your features first, then generate the overlay.
Choose Your Features
CAS login and a JSON service registry are included in this guide. Select any additions below; their instructions
will appear in the following steps. You can return here and change your choices at any time.
Interrupt notifications use Groovy Scripting, and CAS uses one ticket registry, so Redis and Hazelcast exclude each
other; the wizard adjusts your selection and tells you when it does. Without JavaScript, all optional recipes are shown.
curl https://getcas.apereo.org/starter.tgz -dtype=cas-overlay -dbaseDir=cas \-dcasVersion="${CAS_VERSION:?set CAS_VERSION as in step 1}"\-ddependencies=webapp-tomcat,support-json-service-registry | tar-xzvf -
cd cas
The command includes the modules of the features you selected, and step 6 lists them again with all of your
settings. The module snippets in the next steps show what each feature adds; you need them only to extend an overlay
you already have. Without JavaScript, the command includes the JSON service registry alone.
3. Configure CAS
CAS reads its settings from /etc/cas/config/cas.properties; the directory can be changed with
cas.standalone.configuration-directory. Create the directories once, owned by the account that
runs CAS, and then the file:
cas.server.name is the address users reach CAS at, and cas.server.prefix adds
the /cas context path. Plain HTTP is only for trying CAS locally; a deployment must use HTTPS.
OpenID Connect Provider
Add the OIDC module to the dependencies block in build.gradle:
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-oidc"}
CAS creates the signing keystore if it is missing; keep this directory writable by CAS and protect the generated
private keys. See OIDC and
JWKS storage.
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-saml-idp"}
Create a directory owned by the CAS process for its generated metadata, certificates and private keys:
Keep the generated files across restarts. The entity id is CAS’s stable SAML identifier; the IdP metadata endpoint
is http://localhost:8080/cas/idp/metadata. Register your service provider in step 4 before attempting SSO.
See SAML2 Identity Provider.
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-core-scripting"}
Many CAS features accept Apache Groovy scripts: attribute release,
access strategies, interrupt notifications and more. This module adds the Groovy runtime; without it, any configured
script fails when CAS runs it. CAS compiles a script once, caches it and reloads a script file when it changes.
Scripts run with the full privileges of the CAS process, so keep them in a directory only administrators can write,
such as /etc/cas/config. The interrupt recipe in step 5 uses a Groovy script.
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-redis-ticket-registry"}
Start a local Redis instance in a separate terminal (port 6379 must be free):
1
docker run --rm--name cas-quickstart-redis -p 127.0.0.1:6379:6379 redis:7-alpine redis-server --maxmemory-policy noeviction
Keep Redis running while using CAS. This disposable container loses its data when removed. For a deployment,
configure persistence, authentication, TLS and shared ticket encryption keys; see
Redis Ticket Registry. CAS uses one ticket registry: choose Redis or
Hazelcast, not both.
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-hazelcast-ticket-registry"}
Hazelcast runs inside the CAS process: each CAS node is a cluster member, so there is no separate server to start.
Port 5701 must be free. Append to cas.properties to keep this single node in a cluster of its own:
Tickets live in memory and survive only while at least one member runs; a single node loses them on restart.
CAS signs and encrypts tickets in Hazelcast, generating keys at startup when none are set. For a cluster, list every
node in cas.ticket.registry.hazelcast.cluster.network.members or use
auto discovery, and give every node the same
cas.ticket.registry.hazelcast.crypto.encryption.key and
cas.ticket.registry.hazelcast.crypto.signing.key; see
Hazelcast Ticket Registry. CAS uses one ticket registry: choose
Hazelcast or Redis, not both.
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-palantir"}
Append to cas.properties, replacing the example password before starting CAS:
These are separate administrator credentials, not the casuser login. Palantir uses actuator endpoints;
keep them authenticated and restrict exposure before deployment. See the Admin Console.
4. Register an Application
CAS only issues tickets to applications it knows. Add the JSON service registry to the dependencies block of
build.gradle:
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-json-service-registry"}
Point it at the services directory in cas.properties:
Then describe the application in /etc/cas/services/Example-1.json. The serviceId is a regular expression
matched against the address the application sends to CAS:
Replace the secret and configure your OIDC client with the same value. The callback must match your application’s
actual redirect URI. This local HTTP example is for evaluation; use HTTPS in deployment.
See OIDC Clients.
Register a SAML2 Service Provider
Export metadata from your SAML application and save it as /etc/cas/config/saml/sp-metadata.xml.
Use metadata obtained from the application administrator; it supplies the trusted assertion consumer endpoints
and certificates. Replace the example entity id below with the exact SP entity id, escaped as a regular expression.
Create /etc/cas/services/SamlExample-3.json:
Import CAS’s IdP metadata into the application and configure it to trust CAS’s signing certificate.
The example entity id is a placeholder; you need a running SP to complete this recipe.
See SAML2 Service Management.
5. Customize Login
Keep the built-in casuser / Mellon account for a first run, or select LDAP in step 2.
The interrupt notification works with either authentication source.
Connect Your Directory
This step is optional. Out of the box, CAS accepts the single account set in
cas.authn.accept.users. To log in with LDAP accounts instead, add the LDAP module:
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-ldap"}
Then turn off the built-in account and describe your directory:
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-interrupt-webflow"}
This recipe decides with a Groovy script, so it needs the Groovy Scripting module from step 3 as well.
Append to cas.properties:
Create /etc/cas/config/interrupt.groovy. CAS runs it after every successful authentication and passes the
principal, its attributes, the requesting service and its registration, the webflow context and a logger:
1
2
3
4
5
6
7
8
importorg.apereo.cas.interrupt.InterruptResponsedefrun(finalObject...args){def(principal,attributes,service,registeredService,requestContext,logger)=argslogger.info("Showing the quick-start notice to [{}]",principal.id)defmessage="Welcome to your CAS evaluation, ${principal.id}. Continue to your application when ready."returnnewInterruptResponse(message.toString(),[:],false,true)}
The script greets whoever signs in, whether from the built-in account, LDAP or another source. The last two
arguments keep the notice non-blocking and single sign-on enabled. Return InterruptResponse.none() to let a login
through without a notice, for example after checking attributes or service. CAS reloads the file when it
changes. Authentication Interrupt explains blocking policies and
other sources; see the Groovy strategy for its arguments.
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-passwordless-webflow"}
For a local demo, start the same mail catcher used by the CAS browser scenarios. It captures mail without
sending it to a real recipient:
1
docker run --rm--name cas-quickstart-mail -p 127.0.0.1:25000:25000 -p 127.0.0.1:8282:8282 mmoayyed/mockmock:latest
Append to cas.properties:
1
2
3
4
5
6
7
spring.mail.host=localhostspring.mail.port=25000cas.authn.passwordless.tokens.mail.from=cas@example.orgcas.authn.passwordless.tokens.mail.subject=CAS sign-in codecas.authn.passwordless.tokens.mail.html=falsecas.authn.passwordless.tokens.mail.text=Your sign-in code is ${token}cas.authn.passwordless.accounts.json.location=file:/etc/cas/config/passwordless-accounts.json
With this module enabled, eligible applications use the passwordless login flow: enter casuser and the emailed
code instead of Mellon. LDAP credentials are not used for this JSON-backed account. The explicit delegation
setting keeps this account on the email-code path even when you also install an external provider.
Use an account store with verified contact details and a real, secured mail transport for deployment.
See Passwordless Authentication and
per-application controls to retain password login
for selected applications. Installing the Redis ticket registry does not by itself persist passwordless accounts
or configure a shared passwordless token store.
Delegated Authentication
This recipe makes CAS an OIDC client of an external identity provider. The separate OpenID Connect feature in
this wizard makes CAS the provider for your applications; either or both may be installed.
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-pac4j-oidc"}
Register CAS as a confidential client at your external OIDC provider. Allow the callback
http://localhost:8080/cas/login?client_name=ExternalOidc (use your actual HTTPS CAS origin when configured).
Append to cas.properties with the client credentials and discovery URL supplied by that provider:
You need a reachable provider and a user allowed to sign in there; the discovery URL above is a placeholder.
The callback must match the provider’s registered redirect URI exactly. See
generic OIDC delegation for provider-specific settings,
and Delegated Authentication for SAML2, CAS and other providers.
If you also select passwordless authentication, add this second entry alongside casuser in
passwordless-accounts.json to route a separate demo account to the external provider:
Merge the delegateduser entry into the existing JSON object; do not replace the casuser entry.
The external provider still authenticates the user and determines the resulting identity.
See passwordless delegation.
Try MFA Per Application
Each selected MFA recipe below registers its own demo application. You can enable several providers together
and test each separately without changing the baseline Example-1.json application. Adding a module alone does
not require MFA: the application’s multifactorPolicy activates it. See
per-application MFA triggers.
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-gauth"}
Use Google Authenticator or another TOTP application. The default device repository is in memory, suitable for
this local demo; registrations disappear when CAS restarts. Keep credential encryption enabled (the default).
For deployment, configure persistent device storage and stable
cas.authn.mfa.gauth.crypto.encryption.key and
cas.authn.mfa.gauth.crypto.signing.key values.
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-webauthn"}
Use a WebAuthn-capable browser and a security key or platform authenticator. Browsers treat http://localhost as a
secure context, so this recipe works with the HTTP server from step 3. CAS derives the relying-party id, the allowed
origins and the application id from cas.server.name; set
cas.authn.mfa.web-authn.core.relying-party-id and
cas.authn.mfa.web-authn.core.allowed-origins only when they must differ. Credentials are bound to
the relying-party id, so always open CAS at http://localhost:8080, not 127.0.0.1, when registering and using them.
The demo explicitly accepts untrusted attestation so authenticators without a trusted
attestation chain can enroll; choose an attestation policy
for deployment. Default registrations are in memory and disappear on restart; configure
persistent registration storage for a deployment, served over
HTTPS.
This recipe uses WebAuthn as a second factor after the password.
dependencies{/*
The following platform references are included automatically and are listed for reference only.
implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
*/implementation"org.apereo.cas:cas-server-support-duo"}
Create a Duo application for Universal Prompt and obtain its client id, client secret and API hostname.
Use a CAS URL and callback accepted by your Duo application’s configuration. For a deployment, configure a trusted
HTTPS endpoint using the servlet container guide.
If you serve CAS from another origin, update cas.server.name, the OIDC issuer and the SAML entity id
as applicable, and use the new origin for every login URL in this guide.
Append to cas.properties, replacing the placeholders with your Duo application’s values:
The primary CAS username must match a user allowed by your Duo policy. Enroll that user’s device in Duo;
CAS needs network access to the Duo API. These are Universal Prompt credentials, not Duo Admin API credentials.
See Duo Security.
This policy requires mfa-duo for this demo application’s URL. Test it in step 7.
6. Build and Run
Before building, check that you added the modules and files for every selected feature. All property snippets
belong in the same /etc/cas/config/cas.properties file; all module snippets belong in the overlay’s dependencies block.
Both are assembled below for your selection; the JSON and Groovy files from steps 4 and 5 are created separately.
Your overlay’s dependencies block in build.gradle:
Open http://localhost:8080/cas/login?service=https://app.example.org/ and log in. CAS sends the browser back to
the application with a ticket parameter. The example application does not exist, so copy the ST-… ticket from
the address bar and validate it the way an application would:
The response names the user in <cas:user>. A service ticket works once and only for a few seconds, as set by
cas.ticket.st.time-to-kill-in-seconds; log in again if CAS reports it as invalid. The
CAS Protocol describes this exchange in full.
The issuer should be http://localhost:8080/cas/oidc. Configure an OIDC application with that issuer,
client id quickstart-client, your chosen secret, redirect URI http://localhost:9000/callback, scope openid
and authorization-code flow. Start login from that application and confirm it receives and validates an ID token.
Discovery alone does not test a full login; the callback must be served by your OIDC application.
Verify the Notice
Log out at http://localhost:8080/cas/logout, then log in again as any user. Confirm the notice greets that user
by name and that Continue lets you proceed to the application. The CAS log shows the script’s
Showing the quick-start notice line for each login.
Verify Redis Tickets
After logging in, inspect ticket keys without displaying ticket contents:
Expect ticket keys while the login session is active. Check the CAS startup logs if no keys appear.
Verify Hazelcast Tickets
While CAS runs, its embedded Hazelcast member listens on port 5701:
1
lsof -nP-iTCP:5701 -sTCP:LISTEN
Expect one java process. Log in, then stop and start CAS and open http://localhost:8080/cas/login again: CAS asks
you to log in, because a single member keeps tickets only in memory. Tickets survive the loss of a node only in a
cluster of two or more.
Open Palantir
Open http://localhost:8080/cas/palantir and sign in as casadmin with the administrator password you chose.
Confirm the dashboard loads and inspect your registered applications. Available panels depend on the modules installed.
Confirm the metadata contains your configured entity id. Start an SP-initiated login from the application
registered in step 4, authenticate at CAS and confirm the SP accepts the signed response and establishes a
session. Downloading metadata alone does not verify SSO.
Verify MFA with Google Authenticator
Log out of CAS, then open http://localhost:8080/cas/login?service=https://gauth.example.org/ and enter your
primary credentials. On first use, scan the enrollment QR code with your authenticator application and confirm a current code.
Log out and log in again; verify that CAS requires a new TOTP code from the registered device.
The demo application URL is a placeholder: a redirect carrying a ticket shows that CAS completed login.
Validate it using step 7’s p3/serviceValidate command with service=https://gauth.example.org/ and the new ticket.
Verify MFA with WebAuthn
Log out of CAS, then open http://localhost:8080/cas/login?service=https://webauthn.example.org/ and enter your
primary credentials. On first use, complete device registration using the browser prompt. Log out and log in again; verify that
CAS asks you to use the registered authenticator after your password.
The demo application URL is a placeholder: a redirect carrying a ticket shows that CAS completed login.
Validate it using step 7’s p3/serviceValidate command with service=https://webauthn.example.org/ and the new ticket.
Verify MFA with Duo Security
Log out of CAS, then open http://localhost:8080/cas/login?service=https://duo.example.org/ and enter your
primary credentials. Confirm CAS redirects to Duo Universal Prompt. Complete an enrolled factor and verify that Duo returns you
to CAS and CAS issues the service ticket. Use your configured CAS origin if it differs from localhost.
The demo application URL is a placeholder: a redirect carrying a ticket shows that CAS completed login.
Validate it using step 7’s p3/serviceValidate command with service=https://duo.example.org/ and the new ticket.
Verify Passwordless Authentication
Log out, then open http://localhost:8080/cas/login?service=https://app.example.org/ (or your configured HTTPS origin).
Enter casuser. Open the local mail catcher at http://localhost:8282, read the newest sign-in code and enter it
at CAS. Confirm CAS issues a service ticket without asking for Mellon. When trying the MFA demo applications, follow the additional provider prompt required by their application policy.
Keep the mail catcher running while testing and replace it with a real mail service before deployment.
Verify Delegated Authentication
Log out and open http://localhost:8080/cas/login?service=https://app.example.org/, using your configured CAS origin.
Choose ExternalOidc, authenticate at the external provider and confirm you return through CAS to the application
with a service ticket. If passwordless authentication is also selected, enter delegateduser from the combined
account example instead to start delegation. Validate the ticket as shown above and confirm the returned principal
is the identity expected from your external provider.
8. Before Production
Set your own signing and encryption keys for the single sign-on cookie and the login flow:
cas.tgc.crypto.encryption.key, cas.tgc.crypto.signing.key,
cas.webflow.crypto.encryption.key and cas.webflow.crypto.signing.key.
When they are missing, CAS generates them at startup and logs them; keep those values and use them on every node.
Serve CAS over HTTPS only, through the embedded
or an external servlet container.
With more than one node, choose a shared ticket registry
and keep the service definitions identical on every node.
Also replace demo accounts and client secrets, protect the OIDC keystore, secure and persist Redis, configure Hazelcast
cluster membership with shared ticket keys, keep Groovy scripts writable only by administrators, and restrict
Palantir and actuator access when you enable these features. Protect SAML signing keys, persist MFA device
registrations, keep Google Authenticator encryption keys stable and configure your WebAuthn attestation and Duo access policies.