Multifactor Authentication Trusted Device/Browser

In addition to triggers that are provided by the MFA functionality of CAS, there may be cases where you wish to let the user decide if the current browser/device should be trusted so as to skip subsequent MFA requests. The objective is for CAS to remember that decision for a configurable period of time and not bother the user with MFA until the decision is either forcefully revoked or considered expired.

Trusting a device during an MFA workflow would mean that the ultimate decision is remembered for that user of that location of that device. These keys are combined together securely and assigned to the final decision.

Before deployment, you should consider the following:

  • Should users be optionally allowed to authorize the “current” device?
  • …or must that happen automatically once MFA is commenced?
  • How should user decisions and choices be remembered? Where are they stored?
  • How long should user decisions be trusted by CAS?
  • How is a trusted authentication session communicated back to an application?

Note that enabling this feature by default means it’s globally applied to all in the case if you have multiple MFA providers turned on. This can be optionally disabled and applied only to a selected set of providers.


Support is provided via the following module:

implementation "org.apereo.cas:cas-server-support-trusted-mfa:${project.'cas.version'}"
dependencyManagement {
  imports {
    mavenBom "org.apereo.cas:cas-server-support-bom:${project.'cas.version'}"

dependencies {  
  implementation "org.apereo.cas:cas-server-support-trusted-mfa"

Administrative Endpoints

The following endpoints are provided by CAS:

Endpoint Description
multifactorTrustedDevices Expose devices currently registered and trusted by the CAS multifactor authentication engine. A GET operation produces a list of all trusted devices. Specifying a username in the URL as the placeholder/selector will fetch devices registered for that user (i.e. multifactorTrustedDevices/{username}). A DELETE operation with a device key id will attempt to remove the trusted device (i.e. multifactorTrustedDevices/{id}).


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.authn.mfa.trusted.crypto.encryption.key=
  • The encryption key is a JWT whose length is defined by the signing key size setting.

  • cas.authn.mfa.trusted.crypto.signing.key=
  • The signing key is a JWT whose length is defined by the signing key size setting.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.crypto.encryption.key=
  • The encryption key is a JWT whose length is defined by the signing key size setting.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.crypto.signing.key=
  • The signing key is a JWT whose length is defined by the signing key size setting.

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

  • cas.authn.mfa.trusted.couch-db.db-name=
  • Database name.

  • cas.authn.mfa.trusted.couch-db.password=
  • Password for connection.

  • cas.authn.mfa.trusted.couch-db.url=http://localhost:5984
  • Connection url.

  • cas.authn.mfa.trusted.couch-db.username=
  • Username for connection.

  • cas.authn.mfa.trusted.dynamo-db.credential-access-key=
  • Use access-key provided by AWS to authenticate.

  • cas.authn.mfa.trusted.dynamo-db.credential-secret-key=
  • Use secret key provided by AWS to authenticate.

  • cas.authn.mfa.trusted.dynamo-db.endpoint=
  • AWS custom endpoint.

  • cas.authn.mfa.trusted.dynamo-db.region=
  • AWS region used.

  • The endpoint URL to contact and retrieve attributes.

  • cas.authn.mfa.trusted.jpa.driver-class=org.hsqldb.jdbcDriver
  • The JDBC driver used to connect to the database.

  • cas.authn.mfa.trusted.jpa.password=
  • The database connection password.

  • cas.authn.mfa.trusted.jpa.url=jdbc:hsqldb:mem:cas-hsql-database
  • The database connection URL.

  • cas.authn.mfa.trusted.jpa.user=sa
  • The database user.

    The database user must have sufficient permissions to be able to handle schema changes and updates, when needed.

  • cas.authn.mfa.trusted.redis.cluster.nodes[0].host=
  • Server's host address.

  • cas.authn.mfa.trusted.redis.cluster.nodes[0].port=
  • Server's port number.

  • cas.authn.mfa.trusted.redis.cluster.nodes[0].replica-of=
  • Set the id of the master node.

  • cas.authn.mfa.trusted.redis.cluster.nodes[0].type=
  • Indicate the type/role of this node. Accepted values are: MASTER, SLAVE.

  • cas.authn.mfa.trusted.redis.cluster.password=
  • The cluster connection's password.

  • cas.authn.mfa.trusted.redis.pool.enabled=false
  • Enable the pooling configuration.

  • cas.authn.mfa.trusted.redis.sentinel.master=
  • Name of Redis server.

  • cas.authn.mfa.trusted.redis.database=0
  • Database index used by the connection factory.

  • Redis server host.

  • cas.authn.mfa.trusted.redis.password=
  • Login password of the redis server.

  • cas.authn.mfa.trusted.redis.port=6379
  • Redis server port.

  • cas.authn.mfa.trusted.mongo.client-uri=
  • The connection uri to the mongodb instance. This typically takes on the form of mongodb:// If not specified, will fallback onto other individual settings. If specified, takes over all other settings where applicable.

  • cas.authn.mfa.trusted.mongo.collection=
  • MongoDb database collection name to fetch and/or create.

  • cas.authn.mfa.trusted.mongo.database-name=
  • MongoDb database instance name.

  • MongoDb database host for authentication. Multiple host addresses may be defined, separated by comma. If more than one host is defined, it is assumed that each host contains the port as well, if any. Otherwise the configuration may fallback onto the port defined.

  • cas.authn.mfa.trusted.mongo.password=
  • MongoDb database password for authentication.

  • cas.authn.mfa.trusted.mongo.port=27017
  • MongoDb database port.

  • cas.authn.mfa.trusted.mongo.user-id=
  • MongoDb database user for authentication.

    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.

  • cas.authn.mfa.trusted.cleaner.schedule.enabled=true
  • Whether scheduler is should schedule the job to run.

  • cas.authn.mfa.trusted.cleaner.schedule.repeat-interval=PT2M
  • String representation of a repeat interval of re-loading data for an data store implementation. This is the timeout between consecutive job’s executions.

  • cas.authn.mfa.trusted.cleaner.schedule.start-delay=PT15S
  • String representation of a start delay of loading data for a data store implementation. This is the delay between scheduler startup and first job’s execution

  • cas.authn.mfa.trusted.crypto.alg=
  • The signing/encryption algorithm to use.

  • cas.authn.mfa.trusted.crypto.enabled=true
  • Whether crypto operations are enabled.

  • cas.authn.mfa.trusted.crypto.encryption.key-size=512
  • The encryption key size.

  • cas.authn.mfa.trusted.crypto.signing.key-size=512
  • The signing key size.

  • cas.authn.mfa.trusted.crypto.strategy-type=ENCRYPT_AND_SIGN
  • Control the cipher sequence of operations. The accepted values are:

    • ENCRYPT_AND_SIGN: Encrypt the value first, and then sign.
    • SIGN_AND_ENCRYPT: Sign the value first, and then encrypt.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.crypto.alg=
  • The signing/encryption algorithm to use.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.crypto.enabled=true
  • Whether crypto operations are enabled.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.crypto.encryption.key-size=512
  • The encryption key size.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.crypto.signing.key-size=512
  • The signing key size.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.crypto.strategy-type=ENCRYPT_AND_SIGN
  • Control the cipher sequence of operations. The accepted values are:

    • ENCRYPT_AND_SIGN: Encrypt the value first, and then sign.
    • SIGN_AND_ENCRYPT: Sign the value first, and then encrypt.

  • cas.authn.mfa.trusted.jpa.pool.max-size=18
  • Controls the maximum number of connections to keep in the pool, including both idle and in-use connections.

  • cas.authn.mfa.trusted.jpa.pool.max-wait=PT2S
  • Sets the maximum time in seconds that this data source will wait while attempting to connect to a database.

    A value of zero specifies that the timeout is the default system timeout if there is one; otherwise, it specifies that there is no timeout.

  • cas.authn.mfa.trusted.jpa.pool.min-size=6
  • Controls the minimum size that the pool is allowed to reach, including both idle and in-use connections.

  • cas.authn.mfa.trusted.jpa.pool.suspension=false
  • Whether or not pool suspension is allowed.

    There is a performance impact when pool suspension is enabled. Unless you need it (for a redundancy system for example) do not enable it.

  • cas.authn.mfa.trusted.jpa.pool.timeout-millis=1000
  • The maximum number of milliseconds that the pool will wait for a connection to be validated as alive.

  • cas.authn.mfa.trusted.authentication-context-attribute=isFromTrustedMultifactorAuthentication
  • If an MFA request is bypassed due to a trusted authentication decision, applications will receive a special attribute as part of the validation payload that indicates this behavior. Applications must further account for the scenario where they ask for an MFA mode and yet don’t receive confirmation of it in the response given the authentication session was trusted and MFA bypassed.

  • cas.authn.mfa.trusted.device-fingerprint.client-ip.enabled=false
  • Is this component enabled or not.

  • cas.authn.mfa.trusted.device-fingerprint.client-ip.order=0
  • Indicates the order of components when generating a device fingerprint.

  • cas.authn.mfa.trusted.device-fingerprint.component-separator=@
  • Component Separator for device fingerprints.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.comment=CAS Cookie
  • CAS Cookie comment, describes the cookie's usage and purpose.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.domain=
  • Cookie domain. Specifies the domain within which this cookie should be presented. The form of the domain name is specified by RFC 2965. A domain name begins with a dot ( and means that the cookie is visible to servers in a specified Domain Name System (DNS) zone (for example,, but not By default, cookies are only returned to the server that sent them.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.enabled=true
  • Is this component enabled or not.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.http-only=true
  • true if this cookie contains the HttpOnly attribute. This means that the cookie should not be accessible to scripting engines, like javascript.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.max-age=-1
  • The maximum age of the cookie, specified in seconds. By default, -1 indicating the cookie will persist until browser shutdown. A positive value indicates that the cookie will expire after that many seconds have passed. Note that the value is the maximum age when the cookie will expire, not the cookie's current age. A negative value means that the cookie is not stored persistently and will be deleted when the Web browser exits. A zero value causes the cookie to be deleted.

  • Cookie name. Constructs a cookie with a specified name and value. The name must conform to RFC 2965. That means it can contain only ASCII alphanumeric characters and cannot contain commas, semicolons, or white space or begin with a $ character. The cookie's name cannot be changed after creation. By default, cookies are created according to the RFC 2965 cookie specification. Cookie names are automatically calculated assigned by CAS at runtime, and there is usually no need to customize the name or assign it a different value unless a special use case warrants the change.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.order=1
  • Indicates the order of components when generating a device fingerprint.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.path=
  • Cookie path. Specifies a path for the cookie to which the client should return the cookie. The cookie is visible to all the pages in the directory you specify, and all the pages in that directory's subdirectories. A cookie's path must include the servlet that set the cookie, for example, /catalog, which makes the cookie visible to all directories on the server under /catalog. Consult RFC 2965 (available on the Internet) for more information on setting path names for cookies.

  • When generating cookie values, determine whether the value should be compounded and signed with the properties of the current session, such as IP address, user-agent, etc.

  • cas.authn.mfa.trusted.device-fingerprint.cookie.same-site-policy=
  • If a cookie is only intended to be accessed in a first party context, the developer has the option to apply one of settings SameSite=Lax or SameSite=Strict or SameSite=None to prevent external access.

    To safeguard more websites and their users, the new secure-by-default model assumes all cookies should be protected from external access unless otherwise specified. Developers must use a new cookie setting, SameSite=None, to designate cookies for cross-site access. When the SameSite=None attribute is present, an additional Secure attribute is used so cross-site cookies can only be accessed over HTTPS connections.

    Accepted values are: Lax, Strict, None.

  • True if sending this cookie should be restricted to a secure protocol, or false if the it can be sent using any protocol.

  • cas.authn.mfa.trusted.device-fingerprint.geolocation.enabled=false
  • Is this component enabled or not.

  • cas.authn.mfa.trusted.device-fingerprint.geolocation.order=0
  • Indicates the order of components when generating a device fingerprint.

  • cas.authn.mfa.trusted.device-fingerprint.user-agent.enabled=false
  • Is this component enabled or not.

  • cas.authn.mfa.trusted.device-fingerprint.user-agent.order=0
  • Indicates the order of components when generating a device fingerprint.

  • cas.authn.mfa.trusted.device-registration-enabled=true
  • Indicates whether CAS should ask for device registration consent or execute it automatically.

  • cas.authn.mfa.trusted.key-generator-type=default
  • Indicates how record keys for trusted devices would be generated so they can be signed/verified on fetch operations. Acceptable values are default, legacy. *

    • DEFAULT: Uses a combination of the username, device name and device fingerprint to generate the device key.
    • LEGACY: Deprecated. Uses a combination of the username, record date and device fingerprint to generate the device key.

  • cas.authn.mfa.trusted.mongo.pool.idle-time=30000
  • The maximum idle time of a pooled connection. A zero value indicates no limit to the idle time. A pooled connection that has exceeded its idle time will be closed and replaced when necessary by a new connection.

  • The maximum time a pooled connection can live for. A zero value indicates no limit to the life time. A pooled connection that has exceeded its life time will be closed and replaced when necessary by a new connection.

  • cas.authn.mfa.trusted.mongo.pool.max-size=10
  • Maximum number of connections to keep around.

  • cas.authn.mfa.trusted.mongo.pool.max-wait-time=60000
  • The maximum time that a thread may wait for a connection to become available.

  • cas.authn.mfa.trusted.mongo.pool.min-size=1
  • Minimum number of connections to keep around.

  • cas.authn.mfa.trusted.mongo.pool.per-host=10
  • Total number of connections allowed per host.

  • cas.authn.mfa.trusted.couch-db.caching=false
  • Use a local cache to reduce fetches..

  • cas.authn.mfa.trusted.couch-db.cleanup-idle-connections=true
  • Remove idle connections from pool.

  • cas.authn.mfa.trusted.couch-db.connection-timeout=1000
  • TCP connection timeout.

  • cas.authn.mfa.trusted.couch-db.create-if-not-exists=true
  • Create the database if it doesn't exist.

  • cas.authn.mfa.trusted.couch-db.enable-ssl=false
  • Use TLS. Only needed if not specified by URL.

  • cas.authn.mfa.trusted.couch-db.max-cache-entries=1000
  • Max entries in local cache.

  • cas.authn.mfa.trusted.couch-db.max-connections=20
  • Maximum connections to CouchDB.

  • cas.authn.mfa.trusted.couch-db.max-object-size-bytes=8192
  • Largest allowable serialized object.

  • cas.authn.mfa.trusted.couch-db.proxy-host=
  • Proxy host.

  • cas.authn.mfa.trusted.couch-db.proxy-port=-1
  • proxy port.

  • cas.authn.mfa.trusted.couch-db.relaxed-ssl-settings=false
  • Relax TLS settings–like certificate verification.

  • cas.authn.mfa.trusted.couch-db.retries=5
  • Retries for update conflicts.

  • cas.authn.mfa.trusted.couch-db.socket-timeout=10000
  • Socket idle timeout.

  • cas.authn.mfa.trusted.couch-db.use-expect-continue=true
  • Expect HTTP 100 Continue during connection.

  • cas.authn.mfa.trusted.dynamo-db.client-execution-timeout=10000
  • Client execution timeout.

  • cas.authn.mfa.trusted.dynamo-db.connection-timeout=5000
  • Connection timeout.

  • cas.authn.mfa.trusted.dynamo-db.drop-tables-on-startup=false
  • Flag that indicates whether to drop tables on start up.

  • cas.authn.mfa.trusted.dynamo-db.local-address=
  • Local address.

  • cas.authn.mfa.trusted.dynamo-db.local-instance=false
  • Indicates that the database instance is local to the deployment that does not require or use any credentials or other configuration other than host and region. This is mostly used during development and testing.

  • cas.authn.mfa.trusted.dynamo-db.max-connections=10
  • Maximum connections setting.

  • cas.authn.mfa.trusted.dynamo-db.prevent-table-creation-on-startup=false
  • Flag that indicates whether to prevent CAS from creating tables.

  • cas.authn.mfa.trusted.dynamo-db.profile-name=
  • Profile name to use.

  • cas.authn.mfa.trusted.dynamo-db.profile-path=
  • Profile path.

  • cas.authn.mfa.trusted.dynamo-db.proxy-host=
  • Optionally specifies the proxy host to connect through.

  • cas.authn.mfa.trusted.dynamo-db.proxy-password=
  • Optionally specifies the proxy password to connect through.

  • cas.authn.mfa.trusted.dynamo-db.proxy-username=
  • Optionally specifies the proxy username to connect through.

  • Read capacity.

  • cas.authn.mfa.trusted.dynamo-db.retry-mode=STANDARD
  • Outline the requested retry mode. Accepted values are STANDARD, LEGACY.

  • cas.authn.mfa.trusted.dynamo-db.socket-timeout=5000
  • Socket timeout.

  • cas.authn.mfa.trusted.dynamo-db.table-name=DynamoDbCasMfaTrustRecords
  • The table name used and created by CAS to hold mfa trust definitions in DynamoDb.

  • cas.authn.mfa.trusted.dynamo-db.time-offset=0
  • Time offset.

  • cas.authn.mfa.trusted.dynamo-db.use-reaper=false
  • Flag that indicates whether to use reaper.

  • cas.authn.mfa.trusted.dynamo-db.write-capacity=10
  • Write capacity.

  • If REST endpoint is protected via basic authentication, specify the password for authentication.

  • If REST endpoint is protected via basic authentication, specify the username for authentication.

  • HTTP method to use when contacting the rest endpoint. Examples include GET, POST, etc.

  • cas.authn.mfa.trusted.jpa.autocommit=false
  • The default auto-commit behavior of connections in the pool. Determined whether queries such as update/insert should be immediately executed without waiting for an underlying transaction.

  • cas.authn.mfa.trusted.jpa.batch-size=5
  • A non-zero value enables use of JDBC2 batch updates by Hibernate. e.g. recommended values between 5 and 30.

  • Attempts to do a JNDI data source look up for the data source name specified. Will attempt to locate the data source object as is, or will try to return a proxy instance of it, in the event that #dataSourceProxy is used.

  • Indicates whether JNDI data sources retrieved should be proxied or returned back verbatim.

  • cas.authn.mfa.trusted.jpa.ddl-auto=update
  • Hibernate feature to automatically validate and exports DDL to the schema. By default, creates and drops the schema automatically when a session is starts and ends

  • cas.authn.mfa.trusted.jpa.default-catalog=
  • Qualifies unqualified table names with the given catalog in generated SQL.

  • cas.authn.mfa.trusted.jpa.default-schema=
  • Qualify unqualified table names with the given schema/tablespace in generated SQL.

  • cas.authn.mfa.trusted.jpa.dialect=org.hibernate.dialect.HSQLDialect
  • The database dialect is a configuration setting for platform independent software (JPA, Hibernate, etc) which allows such software to translate its generic SQL statements into vendor specific DDL, DML.

  • Set the pool initialization failure timeout.

    • Any value greater than zero will be treated as a timeout for pool initialization. The calling thread will be blocked from continuing until a successful connection to the database, or until the timeout is reached. If the timeout is reached, then a PoolInitializationException will be thrown.
    • A value of zero will not prevent the pool from starting in the case that a connection cannot be obtained. However, upon start the pool will attempt to obtain a connection and validate that the connectionTestQuery and connectionInitSql are valid. If those validations fail, an exception will be thrown. If a connection cannot be obtained, the validation is skipped and the the pool will start and continue to try to obtain connections in the background. This can mean that callers to DataSource#getConnection() may encounter exceptions.
    • A value less than zero will not bypass any connection attempt and validation during startup, and therefore the pool will start immediately. The pool will continue to try to obtain connections in the background. This can mean that callers to DataSource#getConnection() may encounter exceptions.
    Note that if this timeout value is greater than or equal to zero (0), and therefore an initial connection validation is performed, this timeout does not override the connectionTimeout or validationTimeout; they will be honored before this timeout is applied. The default value is one millisecond.

  • The SQL query to be executed to test the validity of connections.

  • cas.authn.mfa.trusted.jpa.idle-timeout=PT10M
  • Controls the maximum amount of time that a connection is allowed to sit idle in the pool.

  • cas.authn.mfa.trusted.jpa.isolate-internal-queries=false
  • This property determines whether data source isolates internal pool queries, such as the connection alive test, in their own transaction.

    Since these are typically read-only queries, it is rarely necessary to encapsulate them in their own transaction. This property only applies if #autocommit is disabled.

  • cas.authn.mfa.trusted.jpa.isolation-level-name=ISOLATION_READ_COMMITTED
  • Defines the isolation level for transactions. @see org.springframework.transaction.TransactionDefinition

  • cas.authn.mfa.trusted.jpa.leak-threshold=3000
  • Controls the amount of time that a connection can be out of the pool before a message is logged indicating a possible connection leak.

  • cas.authn.mfa.trusted.jpa.physical-naming-strategy-class-name=org.apereo.cas.hibernate.CasHibernatePhysicalNamingStrategy
  • Fully-qualified name of the class that can control the physical naming strategy of hibernate.

  • cas.authn.mfa.trusted.jpa.propagation-behavior-name=PROPAGATION_REQUIRED
  • Defines the propagation behavior for transactions. @see org.springframework.transaction.TransactionDefinition

  • Additional settings provided by Hibernate in form of key-value pairs.