Multifactor Authentication Bypass
Each multifactor provider is equipped with options to allow for bypass. Once the provider is chosen to honor the authentication request, bypass rules are then consulted to calculate whether the provider should ignore the request and skip MFA conditionally.
Default Bypass
CAS provides a default bypass policy for
each multifactor provider that can be configured through CAS properties.
All providers will consult this policy for bypass events before consulting any other configured bypass providers.
Bypass rules allow for the following options for each provider:
- Skip multifactor authentication based on designated principal attribute names.
- …[and optionally] Skip multifactor authentication based on designated principal attribute values.
- Skip multifactor authentication based on designated authentication attribute names.
- …[and optionally] Skip multifactor authentication based on designated authentication attribute values.
- Skip multifactor authentication depending on method/form of primary authentication execution.
- Skip multifactor authentication depending on the properties of the http request such as remote addr/host and/or header names.
A few examples follow:
- Trigger MFA except when the principal carries an
affiliation
attribute whose value is eitheralum
ormember
. - Trigger MFA except when the principal carries a
superAdmin
attribute. - Trigger MFA except if the method of primary authentication is SPNEGO.
- Trigger MFA except if credentials used for primary authentication are of type
org.example.MyCredential
.
Note that in addition to the above options, some multifactor authentication providers may also skip and bypass the authentication request in the event that the authenticated principal does not quite “qualify” for multifactor authentication. See the documentation for each specific provider to learn more.
Configuration
Multifactor authentication bypass configuration is defined for each provider id. To learn more about the available settings, examine the configuration for your choice of multifactor authentication provider.
Note that ticket validation requests shall successfully go through if multifactor authentication is bypassed for the given provider. In such cases, no authentication context is passed back to the application and additional attributes are supplanted to let the application know multifactor authentication is bypassed for the provider.
Bypass Per Service
MFA Bypass rules can be overridden per application via the CAS service registry. This is useful when MFA may be turned on globally for all applications and services, yet a few selectively need to be excluded. Services whose access should bypass MFA may be defined as such in the CAS service registry:
1
2
3
4
5
6
7
8
9
10
{
"@class" : "org.apereo.cas.services.CasRegisteredService",
"serviceId" : "^(https|imaps)://.*",
"id" : 100,
"multifactorPolicy" : {
"@class" : "org.apereo.cas.services.DefaultRegisteredServiceMultifactorPolicy",
"multifactorAuthenticationProviders" : [ "java.util.LinkedHashSet", [ "mfa-duo" ] ],
"bypassEnabled" : "true"
}
}
Bypass Per Principal Attribute & Service
This is similar to the above option, except that bypass is only activated for the registered application if the authenticated principal contains an attribute with the specified value(s).
1
2
3
4
5
6
7
8
9
10
{
"@class" : "org.apereo.cas.services.CasRegisteredService",
"serviceId" : "^(https|imaps)://.*",
"id" : 100,
"multifactorPolicy" : {
"@class" : "org.apereo.cas.services.DefaultRegisteredServiceMultifactorPolicy",
"bypassPrincipalAttributeName": "attributeForBypass",
"bypassPrincipalAttributeValue": "^bypass-value-[A-Z].+",
}
}
Matching and comparison operations are case insensitive.
Setting the bypassEnabled
flag here is unnecessary and may cause side-effects. Once principal attribute name and match value
are defined, the bypassEnabled
is expected to be true
anyway.
Additional Bypass Providers
In addition to the configurable default bypass rules, the following bypass providers can be defined and executed after default bypass rules are calculated.
In the case where the default rules determine that the multifactor authentication should be bypassed, the chain will be short circuited and no additional bypass providers will be consulted.
Bypass via Groovy
Multifactor authentication bypass may be determined using a Groovy script of your
own design. The outcome of the script, if true
indicates that multifactor
authentication for the requested provider should proceed. Otherwise false
indicates
that multifactor authentication for this provider should be skipped and bypassed.
The outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.*
def boolean run(final Object... args) {
def authentication = args[0]
def principal = args[1]
def registeredService = args[2]
def provider = args[3]
def logger = args[4]
def httpRequest = args[5]
// Stuff happens...
return false;
}
The parameters passed are as follows:
Parameter | Description |
---|---|
authentication |
The object representing the established authentication event. |
principal |
The object representing the authenticated principal. |
service |
The object representing the corresponding service definition in the registry. |
provider |
The object representing the requested multifactor authentication provider. |
logger |
The object responsible for issuing log messages such as logger.info(...) . |
httpRequest |
The object responsible for capturing the http request. |
As an example, the following script skips multifactor authentication if the application
requesting it is registered in the CAS service registry under the name MyApplication
and
only does so if the provider is Duo Security and the authenticated principal contains
an attribute named mustBypassMfa
whose values contains true
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
boolean run(final Object... args) {
def authentication = args[0]
def principal = args[1]
def service = args[2]
def provider = args[3]
def logger = args[4]
def httpRequest = args[5]
if (service.name == "MyApplication") {
logger.info("Evaluating principal attributes ${principal.attributes}")
def bypass = principal.attributes['mustBypassMfa']
if (bypass.contains("true") && provider.id == "mfa-duo") {
logger.info("Skipping bypass for principal ${principal.id}")
return false
}
}
return true
}
Bypass via REST
Multifactor authentication bypass may be determined using a REST API of your
own design. Endpoints must be designed to accept/process application/json
via
GET
requests. A returned status code 202
meaning ACCEPTED
indicates that multifactor
authentication for the requested provider should proceed. Otherwise multifactor
authentication for this provider should be skipped and bypassed.
The following parameters are passed:
Parameter | Description |
---|---|
principal |
The identifier of the authenticated principal. |
provider |
The identifier of the multifactor authentication provider. |
service |
The identifier of the registered service in the registry, if any. |