Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Info

Starting with IdP 4.2 you can the install the latest plugin version supported on your IdP version with
.\plugin.sh -I <PluginId>

Plugin

Plugin ID

Module

ID

(s)

Authentication Flow ID

Latest Version

Bug Reporting

Duo Universal Prompt via the Shibboleth Nimbus Client

net.shibboleth.idp.plugin.authn.duo.nimbus

idp.authn.DuoOIDC

authn/DuoOIDC

1.2.0: download

https://shibboleth.atlassian.net/browse/JDUO

Duo Universal Prompt via the Duo WebSDK v4 Client

net.shibboleth.idp.plugin.authn.duo.sdk

idp.authn.DuoOIDC

authn/DuoOIDC

1.2.0: download

https://shibboleth.atlassian.net/browse/JDUO


The following table highlights the differences in their technical specification to help you decide which to install. Note, their functional specification (how it works for the end-user) is the same for either.

Feature

Duo WebSDK v4

Shibboleth Nimbus

Based on the official SDK

X

Duo Endpoint and Configuration Health Check

X

X

Duo 2FA result token signature (HMAC) checking

X

X

Duo 2FA result token encryption handling (not provided by Duo)

Duo 2FA result token claims verification

X

X

Duo 2FA result token nonce verification

X

Customizable HttpClient implementation

X

Customizable TrustEngine implementation

X

HTTP Public Key Pinning

X

X

Supports TLS Certification Revocation Checking

X

X

Customisable JSON response mapper

X

Include Page
PluginInstallation
PluginInstallation

...

Info

Automatic Flow Registration

The flow definition, default beans, and authentication flow descriptor are loaded automatically from well-known location(s) from the plugin’s classpath. The default behavior configured in those files can be overridden via the two configuration files shown above.

Systems IdP installations upgraded from versions prior to V4.1 are also likely to require adding the idp.searchForProperties=true property to their idp.properties file, or else an explicit reference would have to be added to the new property file added by the module. It's best easiest to clean up the property situation prior to using plugins that add their own.

...

Expand
titleAdvanced Principal Configuration

For a basic configuration, you set the supportedPrincipals property on both the "authn/MFA" and "authn/DuoOIDC" underlying AuthenticationFlowDescriptor objects. These are copied across as Principal objects to the resulting Java Subject after successful authentication. If you need greater granularity, you can configure custom Principal sets in the following ways:

  • Directly on the DuoOIDCIntegration bean. This is useful if you have more than one Duo integration and want one to satisfy a request the other does not, usually due to different policies or factors supported on the Duo end. This works the same as the original Duo integration.

  • Via a strategy function. This allows runtime decisions about Principal to be made from the Duo 2FA result token.

Both are described below.

Directly on the DuoOIDCIntegration

You can define Principal sets per Duo Integration. This is particularly useful if you have more than one integration, and want each to satisfy a different Authentication Context Class Reference requested by a Service Provider. In the examples, the bean properties set are purely examples, they could be set inline or rely on property names of your own choice.

Per Integration Supported Principals
Code Block
languagexml
<bean id="Duo1" parent="shibboleth.authn.DuoOIDC.DuoIntegration" 
		p:APIHost="%{idp.duo.oidc.apiHost:none}"
        p:clientId="%{idp.duo.oidc.clientId:none}"
        p:secretKey="%{idp.duo.oidc.secretKey:none}">
		<property name="supportedPrincipals">
       	 	<list>
          		  <bean parent="shibboleth.SAML2AuthnContextClassRef"
             		   c:classRef="http://example.org/ac/classes/mfa/default" />
            	  <bean parent="shibboleth.SAML1AuthenticationMethod"
                	c:method="http://example.org/ac/classes/mfa/default" />
        	</list>
    	</property>
</bean>

<bean id="Duo2" parent="shibboleth.authn.DuoOIDC.DuoIntegration" 
		p:APIHost="%{idp.second.duo.oidc.apiHost:none}"
        p:clientId="%{idp.second.duo.oidc.clientId:none}" 
        p:secretKey="%{idp.second.duo.oidc.secretKey:none}">
		<property name="supportedPrincipals">
       	 	<list>
          		  <bean parent="shibboleth.SAML2AuthnContextClassRef"
             		   c:classRef="http://example.org/ac/classes/mfa/second" />
        	</list>
    	</property>
</bean>

Context to Principal Mapping Strategy

If you want to add Principals to the Java Subject based on runtime information received inside a Duo result (authentication) token, you can add a Java bean named shibboleth.authn.DuoOIDC.ContextToPrincipalMappingStrategy that could, for example, inspect the JWT ClaimsSet of the Duo token. The type of this bean is Function<ProfileRequestContext,Collection<Principal>> (input is the profile request context tree, and the output is the collection to inject into the Subject).

The following example script adds the ACR "http://example.org/ac/classes/mfa/strong" to the Java Subject if the 'duo_push' two-factor authentication method was used (this is not a commentary on the "strength" of push-based MFA, strictly an example).

Example Context To Principal Mapping Strategy
Code Block
languagexml
<bean id="shibboleth.authn.DuoOIDC.ContextToPrincipalMappingStrategy" parent="shibboleth.ContextFunctions.Scripted" 
        factory-method="inlineScript"
        c:outputType="java.util.Collection"
        p:hideExceptions="false">
        <constructor-arg>
            <value>
        <![CDATA[
            //setup logger and types
            logger = Java.type("org.slf4j.LoggerFactory").getLogger("org.example.duo.script");
            var ArrayList = Java.type("java.util.ArrayList");
            var ACR = Java.type("net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal");
            
            //create new output collection
            var principals = new ArrayList(1);
            
            var ac = input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
            if (ac != null){
                var dc = ac.getSubcontext("net.shibboleth.idp.plugin.authn.duo.context.DuoOIDCAuthenticationContext");
                if (dc != null){
                     if (dc.getAuthToken() != null && "duo_push".equals(dc.getAuthToken().getJWTClaimsSet().getJSONObjectClaim("auth_context").get("factor"))){
                         principals.add(new ACR("http://example.org/ac/classes/mfa/strong"));
                     }
                }
            }
            //return obj is the value of the last expression.
            principals;
         ]]>
            </value>
        </constructor-arg>
</bean>

It is important to note that if the mapping strategy bean is defined, the default supportedPrincipals of the underlying flow descriptor are not added to the Java Subject irrespective of the value of the property idp.authn.DuoOIDC.addDefaultPrincipals. Instead, alongside those added by the Function, only a DuoPrincipal, and any Principals defined on the DuoOIDCIntegration itself are added.

The following JSON listing shows an example of the current Duo JWT ClaimsSet for reference when constructing a mapping strategy. Refer to Duo's documentation as the final word on the subject.

Duo JWT ClaimsSet
Code Block
languagejs
{
    "iss": "https://api.duosecurity.com/oauth/v1/token",
    "sub": "subject",
    "aud": "DDFGGSGERGERR",
    "exp": 1590070939,
    "iat": 1590067340,
    "auth_time": 1590067339,
    "auth_result": {
        "status_msg": "Login Successful",
        "status": "allow",
        "result": "allow"
    },
    "auth_context": {
        "result": "success",
        "timestamp": 1590067339,
        "auth_device": {
            "ip": "100.100.100.12",
            "name": "telephone",
            "location": {
                "state": "State",
                "city": "City",
                "country": "United Kingdom"
            }
        },
        "txid": "b1287968-1dd1-4488-bb3c-0c72fc398b8b",
        "event_type": "authentication",
        "reason": "user_approved",
        "access_device": {
            "ip": "100.100.100.13",
            "location": {
                "state": "State",
                "city": "City",
                "country": "United Kingdom"
            }
        },
        "application": {
            "key": "DDFGGSGERGERR",
            "name": "Duo Integration"
        },
        "factor": "duo_push",
        "user": {
            "key": "DDFGGSGERGERR",
            "name": "username"
        }
    }
}

...

Expand
titleCertificate Revocation Checking

Neither plugin/client is configured by default to check the revocation status of the certificates presented during the TLS handshake. Generally, there are three options for this:

  1. Revocation checking from a Certificate Revocation List defined in a local store.

  2. Revocation checking from a Certificate Revocation List fetched from a distribution point defined in the certificate.

  3. Revocation checking from querying an Online Certificate Status Protocol (OCSP) endpoint defined in the certificate.

To configure revocation checking with the Duo WebSDK v4 plugin, use the normal Java Trust Manager system properties (see the CertPathDocs).

To enable revocation checking with the Shibboleth Nimbus plugin, you will need to set the property idp.duo.oidc.nimbus.checkRevocation to true in the conf/authn/duo-oidc.properties file *and* do one or more of the following:

  1. Add one or more 'approved' (issuer and signature verified) static CRLs as Resources to a list bean named shibboleth.authn.DuoOIDC.tls.CRLs to the conf/authn/duo-oidc-authn-config.xml file.

  2. Enable CRL checking from an online distribution point via the system property com.sun.security.enableCRLDP (as described in the CertPathDocs)

  3. Enable OCSP via the security system property oscp.enabled (as described in the CertPathDocs)

Note that Duo does not support OSCP stapling, so this is not an option at this stage.

...

Derived from properties in 

-authn-config.xml:

Expand
titleBeans (General)

Bean ID / Type

Default

Description

shibboleth.authn.DuoOIDC.DuoIntegration

DuoOIDCIntegration

HTTP Proxy

The HTTPClientBuilder object that is the base for the HTTPClient beans has properties for HTTP proxy settings. To configure a proxy for use by the Nimbus plugin, add this bean to conf/authn/duo-oidc

.properties

Defines a single/static Duo OIDC Integration with Duo, you can override this bean to supply a non-property-configured alternative

shibboleth.authn.DuoOIDC.DuoIntegrationStrategy

Function<ProfileRequestContext,DuoOIDCIntegration>

Optional bean to supply the Duo OIDC integration settings dynamically

Code Block
languagexml
 <bean id="shibboleth.authn.DuoOIDC
.UsernameLookupStrategy

Function<ProfileRequestContext,String>

CanonicalUsernameLookupStrategy

Optional bean to supply username

shibboleth.authn.DuoOIDC.resultCachingPredicate
.nimbus.HttpClient"
        parent="shibboleth.authn.DuoOIDC.nimbus.InternalHttpClient"
           p:connectionProxyHost="proxy.example.org"
           p:connectionProxyPort="3128" />
Expand
titleDuo Health Check (1.3.0+)

Before each Duo 2FA request, a back-channel lookup is made to Duo’s health check endpoint to determine if the Duo servers are accessible and accepting requests. If for some reason they aren’t, the 2FA attempt fails but the IdP’s authentication flows resume. This is a standard part of Duo’s 2FA workflow. The benefit of this approach is, it occurs before the URL redirect in the browser, and if the Duo 2FA endpoint were not available the IdP remains in control of the authentication process. Otherwise, the user’s browser might timeout during the 2FA request, or the user might get stuck on an error page of some kind.

However, this involves an extra, frequent, back-channel network lookup and as such is subject to the same reliability/availability issues as the actual 2FA request. From investigation, it appears possible to bypass this check and still have the 2FA proceed as normal. Consequently, from v1.3.0 onward we have included a property (idp.duo.oidc.healthcheck.enabled) that allows the deployer to turn off this check.

Expand
titleAudit Logging (1.3.0+)

Since v1.3.0 it is possible to enable audit logging for Duo2FA interactions by setting the property idp.duo.oidc.audit.enabled to true in /conf/authn/duo-oidc.properties. From v1.4.0 onward you also need to enable the general authentication audit logging on the IdP using the property idp.authn.audit.enabled in /conf/authn.properties.

Once enabled, audit log statements are routed through a logger named Shibboleth-Audit.DuoOIDC. From v1.4.0 onward, you can change the name of this logger using the property idp.duo.oidc.audit.category in /conf/authn/duo-oidc.properties.

Without further configuration, the audit statements will appear in the normal idp-audit.log log file. This may be sufficient for your needs, if not and you would rather those exclusively appear in a new audit log file, you will need to add a new Logback appender and logger to the logback.xml file, for example:

Code Block
<appender name="IDP_DUO2FA_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${idp.logfiles}/idp-duo2fa-audit.log</File>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${idp.logfiles}/idp-duo2fa-audit-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
            <maxHistory>${idp.loghistory}</maxHistory>
        </rollingPolicy>

        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <charset>UTF-8</charset>
            <Pattern>%msg%n</Pattern>
        </encoder>
</appender>
    
<!-- Set additivity false if you do not want DuoOIDC events in the standard audit log -->
<logger name="Shibboleth-Audit.DuoOIDC" level="ALL" additivity="false">
    <appender-ref ref="${idp.audit.appender:-IDP_DUO2FA_AUDIT}"/>
</logger>

Audit Format

The default audit format is shown below (the fields are described in the table underneath).

Code Block
%AAF|%a|%T|%DuoU|%DuoRedirect|%DuoCID|%DuoReqS|%DuoRespS|%DuoTXID|%DuoDID|%DuoDN|%DuoR|%DuoF

Custom Audit Format V1.3.0

For version 1.3.0, the audit format can be adjusted by specifying your own bean, shibboleth.authn.DuoOIDC.AuditFormattingMap, in /conf/authn/duo-oidc-authn-config.xml.

Custom Audit Format V1.4.0+

For version 1.4.0+, the audit format can be adjusted using the idp.duo.oidc.audit.format property in /conf/authn/duo-oidc.properties.

Audit Logging Fields

Field

Description

AAF

The ID of the currently running authentication flow i.e. authn/DuoOIDC in this case

DuoRedirect

The location of the IdP’s callback endpoint Duo will redirect the user too after successful authentication

DuoCID

The Duo client identifier used for this request

DuoTXID

The transaction ID contained in the Duo 2FA response

DuoDID

The ID of the device used to authenticate the user

DuoDN

The friendly name of the device used to authenticate the user

DuoR

The authentication reason

DuoF

The factor used for 2FA e.g. a Security Key or SMS.

DuoU

The username of the authenticating user sent in the Duo 2FA request

DuoRespS

The state OAuth 2.0 parameter returned in the Duo response

DuoReqS

The state OAuth 2.0 parameter sent to Duo in the 2FA request (client authorization request)

Reference

Expand
titleBeans (General)

Bean ID / Type

Default

Description

shibboleth.authn.DuoOIDC.DuoIntegration

DuoOIDCIntegration

Derived from properties in conf/authn/duo-oidc.properties

Defines a single/static Duo OIDC Integration with Duo, you can override this bean to supply a non-property-configured alternative

shibboleth.authn.DuoOIDC.DuoIntegrationStrategy

Function<ProfileRequestContext,DuoOIDCIntegration>


Optional bean to supply the Duo OIDC integration settings dynamically

shibboleth.authn.DuoOIDC.UsernameLookupStrategy

Function<ProfileRequestContext,String>

CanonicalUsernameLookupStrategy

Optional bean to supply username

shibboleth.authn.DuoOIDC.resultCachingPredicate

Predicate<ProfileRequestContext>

shibboleth.Conditions.TRUE

Bean ID controlling whether to preserve the authentication result in an IdP session

shibboleth.authn.DuoOIDC.CleanUpHook

Consumer<ProfileRequestContext>

Bean that removes the DuoOIDAuthenticationContext from the tree

A cleanup hook that is executed on successful authentication.

shibboleth.authn.DuoOIDC.jwt.claims.CleanUpHook

Consumer<ProfileRequestContext>

Bean that removes the nonce value from the DuoOIDAuthenticationContext

A cleanup hook to execute after either successful or unsuccessful claims validation

shibboleth.authn.DuoOIDC.DuoTokenClaimsVerifier

JWTClaimsValidation

DefaultDuoTokenClaimsVerifier Claims verification in accordance with the Duo specification. Also OIDC compliant for the special Duo id_token case.

Duo result token (OIDC id_token) claims verifier using a 'chain' of ClaimsValidators e.g. audience, issuer, expiration checks etc. You can either replace the claims validator completely, change some of the behavior of existing validators individually, or add to a new validation check using a custom BiFunction, see a custom BiFunction, see shibboleth.authn.DuoOIDC.ExtendedClaimsValidator.

shibboleth.authn.DuoOIDC.jwt.IssuerLookupStrategy

BiFunction<ProfileRequestContextJWTClaimsSet, String>

Combines the HTTPS scheme, with the Duo API Hostname, and the Duo token IssuerPath.

Lookup strategy that returns the OIDC issuer. An issuer contains the scheme, host, and optionally, port and path components that identify the id_token issuer.

shibboleth.authn.DuoOIDC.ExtendedClaimsValidator.jwt.AudienceLookupStrategy

BiFunction<ProfileRequestContext,JWTClaimsSet, String>

The clientID of the Duo Integration pertaining to the request.

Lookup the client_id for the Relying Party.

shibboleth.authn.DuoOIDC.jwt.IssuerLookupStrategyUsernameLookupStrategy

BiFunction<ProfileRequestContext, JWTClaimsSet, String>

Combines the HTTPS scheme, with the Duo API Hostname, and the Duo token IssuerPath.

Lookup strategy that returns the OIDC issuer. An issuer contains the scheme, host, and optionally, port and path components that identify the id_token issuer. String>

The authenticating principal's username from the context pertaining to the request.

Lookup the authenticating principal's username to match Duo's preferred_username field in the id_token.

shibboleth.authn.DuoOIDC.jwt.AuthTimeActivationCondition

BiPredicate<ProfileRequestContext,JWTClaimsSet>

Returns true if forced authentication has been requested by the Relying Party.

Should the auth_time field be validated for the given request?

shibboleth.authn.DuoOIDC.jwt.AudienceLookupStrategyNonceLookupStrategy

BiFunction<ProfileRequestContext,JWTClaimsSet, String>

The clientID of the Duo Integration pertaining to the request.

Lookup the client_id for the Relying Party String>

The nonce that was used in the authorization request and stored in the Duo authentication context.

Lookup the nonce that was used in the authorization request and should be present in the id_token.

shibboleth.authn.DuoOIDC.jwt.UsernameLookupStrategyNonceActivationCondition

BiFunctionBiPredicate<ProfileRequestContext,JWTClaimsSetString>

The authenticating principal's username from the context pertaining to the request.

Lookup the authenticating principal's username to match Duo's preferred_username field in the id_token>

Returns true iff the id_token contains a nonce.

Should we validate the nonce value in the id_token?

shibboleth.authn.DuoOIDC.RequiredOIDCClaims

Set<String>

Used by the DefaultDuoTokenClaimsVerifier above. Defaults to those claims required by the OIDC specification (https://openid.net/specs/openid-connect-core-1_0.html#IDToken)

The names of the claims required to be present in the Duo result token (OIDC id_token).

shibboleth.authn.DuoOIDC.jwt.AuthTimeActivationConditionContextToPrincipalMappingStrategy

BiPredicateFunction<ProfileRequestContext,JWTClaimsSet>

Returns true if forced authentication has been requested by the Relying Party.

Should the auth_time field be validated for the given request?Collection<Principal>>


Map information in the ProfileRequestContext, most likely in the Duo result id_token, to a collection of Principals the execution of the flow supports. See this advanced topic.

shibboleth.authn.DuoOIDC.jwt.NonceLookupStrategyExtendedClaimsValidator

BiFunction<JWTClaimsSet,ProfileRequestContext,JWTClaimsSetString>

The nonce that was used in the authorization request and stored in the Duo authentication context.

Lookup the nonce that was used in the authorization request and should be present in the id_tokenJWTValidationException>


Optional BiFunction extension point for custom claims validation of the Duo token

shibboleth.authn.DuoOIDC.PreDuoPopulateAuditExtractors1.3.0

Map<String,Function<ProfileRequestContext,Object>>

List of Pre-Duo 2FA redirect audit extractors that take the profile request context and return an object (likely a String) to append to the log statement.

shibboleth.authn.DuoOIDC.PostDuoPopulateAuditExtractors1.jwt3.NonceActivationConditionBiPredicate0

Map<String,Function<ProfileRequestContext,JWTClaimsSet>

Returns true iff the id_token contains a nonce.

Should we validate the nonce value in the id_token?Object>>

List of Post-Duo 2FA audit extractors that take the profile request context and return an object (likely a String) to append to the log statement.

shibboleth.authn.DuoOIDC.RequiredOIDCClaims

Set<String>

Used by the DefaultDuoTokenClaimsVerifier above. Defaults to those claims required by the OIDC specification (https://openid.net/specs/openid-connect-core-1_0.html#IDToken)

The names of the claims required to be present in the Duo result token (OIDC id_token)..AuditFormattingMap1.3.0(only)

Map<String, String>

Map of logging categories to audit formatting strings for Duo 2FA audit logging

Expand
titleBeans (Duo WebSDK)

These beans are specific to the Duo WebSDK-based plugin only:

Bean ID / Type

Default

Description

shibboleth.authn.DuoOIDC.sdk.TrustedCertificates

List<String>

DefaultTrustedCertificates

A default list of trust root CA public key hashes. See HTTP Public Key Pinning

Description
Expand
titleBeans (Nimbus)

These beans are specific to the Nimbus-based plugin only:

Bean ID / Type

Default

Description

shibboleth.authn.DuoOIDC

.ContextToPrincipalMappingStrategy

Function<ProfileRequestContext,Collection<Principal>>

Map information in the ProfileRequestContext, most likely in the Duo result id_token, to a collection of Principals the execution of the flow supports. See this advanced topic.

.nimbus.TrustedCertificates

List<Resource>

Default trust list

A default list of trust root CA certificates. See HTTP Public Key Pinning

shibboleth.authn.DuoOIDC.nimbus.

ExtendedClaimsValidator

BiFunction<JWTClaimsSet,ProfileRequestContext,JWTValidationException>

Optional BiFunction extension point for custom claims validation of the Duo token

Expand
titleBeans (Duo WebSDK)

These beans are specific to the Duo WebSDK-based plugin only:

Bean ID / Type

Default

HttpClientSecurityParameters

HttpClientSecurityParameters

Custom security settings for the Duo OIDC calls

shibboleth.authn.DuoOIDC.nimbus.HttpClient

HttpClient

Internal/default HttpClient instance

The HttpClient used to connect to Duo's OIDC endpoints. Properties can be overridden in the duo-oidc.properties file.

shibboleth.authn.DuoOIDC.nimbus.TrustEvaluator

PKIXTrustEvaluator

Default TrustEvaluator

Tied to a TLS Trust Engine and hence the HttpClientSecurityParameters

Evaluates the X509 Credential

shibboleth.authn.DuoOIDC.

sdk

tls.

TrustedCertificatesList<String

CRLs

List<Resource>

DefaultTrustedCertificates

A default

Supplied list of

trust root CA public key hashes. See HTTP Public Key Pinning

static CRL resources. See Certificate Revocation Checking

A default list of trust root CA certificates. See HTTP Public Key Pinning
Expand
titleBeans (NimbusNon-Browser Auth API)

These beans are specific refer to the Nimbus-based plugin only:Duo Auth API (non-OIDC) which supports non-browser flows.

Bean ID / Type

Default

Description

shibboleth.authn.DuoOIDC.

nimbus

NonBrowser.

TrustedCertificates

List<Resource>

Default trust list

DuoIntegration

DuoIntegration

Derived from properties in conf/authn/duo-oidc.properties

Defines a single/static Duo AuthAPI integration for non-browser support

shibboleth.authn.DuoOIDC.

nimbus

NonBrowser.

HttpClientSecurityParameters

HttpClientSecurityParameters

Custom security settings for the Duo OIDC calls

DuoIntegrationStrategy

Function<ProfileRequestContext,DuoIntegration>


Optional bean to supply the Duo AuthAPI integration settings dynamically

shibboleth.authn.DuoOIDC.

nimbus

NonBrowser.HttpClient

HttpClient

Internal/default HttpClient instance

The HttpClient used to connect to Duo's OIDC endpoints. Properties can be overridden in the duo-oidc.properties file.

Overrides the HttpClient implementation and settings to use for the AuthAPI (see HttpClientConfiguration)

shibboleth.authn.DuoOIDC.

nimbus

NonBrowser.

TrustEvaluator

PKIXTrustEvaluator

Default TrustEvaluator

Tied to a TLS Trust Engine and hence the HttpClientSecurityParameters

Evaluates the X509 Credential

shibboleth.authn.DuoOIDC.tls.CRLs

List<Resource>

Supplied list of static CRL resources. See Certificate Revocation Checking

HttpClientSecurityParameters

HttpClientSecurityParameters


Custom security settings for the AuthAPI calls (see HttpClientConfiguration)

These beans refer to the Duo Auth API (non-OIDC) which supports non-browser flows.

The DuoOIDC-specific properties defined in conf/authn/duo-oidc.properties follow:

The properties below are used when enabling non-browser / AuthAPI support:
Expand
titleBeans Properties (NonDuoOIDC-Browser Auth API)

Bean ID / Type

Default

Description

shibboleth.authn.DuoOIDC.NonBrowser.DuoIntegration

DuoIntegration

Derived from properties in conf/authn/duo-oidc.properties

Defines a single/static Duo AuthAPI integration for non-browser support

shibboleth.authn.DuoOIDC.NonBrowser.DuoIntegrationStrategy

Function<ProfileRequestContext,DuoIntegration>

Optional bean to supply the Duo AuthAPI integration settings dynamically

shibboleth.authn.DuoOIDC.NonBrowser.HttpClient

HttpClient

Internal/default HttpClient instance

Overrides the HttpClient implementation and settings to use for the AuthAPI (see HttpClientConfiguration)

shibboleth.authn.DuoOIDC.NonBrowser.HttpClientSecurityParameters

HttpClientSecurityParameters

Custom security settings for the AuthAPI calls (see HttpClientConfiguration)

Expand
titleProperties (DuoOIDC-Specific)

Name

Default

Description

idp.duo.oidc.apiHost

DuoOIDC API hostname assigned to the integration

idp.duo.oidc.clientId

The OAuth 2.0 Client Identifier valid at the Authorization Server

idp.duo.oidc.redirectURL

Redirection URI to which the 2FA response will be sent

idp.duo.oidc.redirecturl.allowedOrigins

If the idp.duo.oidc.redirectURL is not set, one will be computed dynamically and checked against this list of allowed origins - to prevent Http Host Header injection.

idp.duo.oidc.secretKey

The client secret used to verify the client in exchanging the authorization code for a Duo 2FA result token (id_token).

idp.duo.oidc.endpoint.health

/oauth/v1/health_check

Duo's OAuth 2.0 health check endpoint

idp.duo.oidc.endpoint.token

/oauth/v1/token

Duo's OAuth 2.0 token endpoint

idp.duo.oidc.endpoint.authorize

/oauth/v1/authorize

Duo's OAuth 2.0 authorization endpoint

idp.duo.oidc.jwt.verifier.clockSkew

PT60S

Leeway allowed in token expiry calculations

idp.duo.oidc.jwt.verifier.iatWindow

PT60S

Maximum amount (in either direction from now) of duration for which a token is valid after it is issued

idp.duo.oidc.jwt.verifier.issuerPath

/oauth/v1/token

The path component of the Duo token issuer. The full issuer string takes the format: HTTPS://<idp.duo.oidc.apiHost>+<idp.duo.oidc.jwt.verifier.issuerPath>

idp.duo.oidc.jwt.verifier.preferredUsername

preferred_username

The result token JWT claim name that represents the username sent in the duo_uname field in the authorization request.

idp.duo.oidc.jwt.verifier.authLifetime

PT60S

How long the authentication is valid. Only applies to forced authentication requests.

Specific)

The DuoOIDC-specific properties defined in conf/authn/duo-oidc.properties follow:

Name

Default

Description

idp.duo.oidc.apiHost

DuoOIDC API hostname assigned to the integration

idp.duo.oidc.clientId

The OAuth 2.0 Client Identifier valid at the Authorization Server

idp.duo.oidc.redirectURL

Redirection URI to which the 2FA response will be sent

idp.duo.oidc.redirecturl.allowedOrigins


If the idp.duo.oidc.redirectURL is not set, one will be computed dynamically and checked against this list of allowed origins - to prevent Http Host Header injection.

idp.duo.oidc.secretKey


The client secret used to verify the client in exchanging the authorization code for a Duo 2FA result token (id_token).

idp.duo.oidc.endpoint.health

/oauth/v1/health_check

Duo's OAuth 2.0 health check endpoint

idp.duo.oidc.endpoint.token

/oauth/v1/token

Duo's OAuth 2.0 token endpoint

idp.duo.oidc.endpoint.authorize

/oauth/v1/authorize

Duo's OAuth 2.0 authorization endpoint

idp.duo.oidc.jwt.verifier.clockSkew

PT60S

Leeway allowed in token expiry calculations

idp.duo.oidc.jwt.verifier.iatWindow

PT60S

Maximum amount (in either direction from now) of duration for which a token is valid after it is issued

idp.duo.oidc.jwt.verifier.issuerPath

/oauth/v1/token

The path component of the Duo token issuer. The full issuer string takes the format: HTTPS://<idp.duo.oidc.apiHost>+<idp.duo.oidc.jwt.verifier.issuerPath>

idp.duo.oidc.jwt.verifier.preferredUsername

preferred_username

The result token JWT claim name that represents the username sent in the duo_uname field in the authorization request.

idp.duo.oidc.jwt.verifier.authLifetime

PT60S

How long the authentication is valid. Only applies to forced authentication requests.

The properties below are used when enabling non-browser / AuthAPI support:

idp.duo.oidc.nonbrowser.apiHost

${idp.duo.oidc.apiHost}

Duo AuthAPI hostname assigned to the integration

idp.duo.oidc.nonbrowser.integrationKey

Duo AuthAPI integration key (supplied by Duo)

idp.duo.oidc.nonbrowser.secretKey

Duo AuthAPI secret key (supplied by Duo)

idp.duo.oidc.nonbrowser.header.factor

X-Shibboleth-Duo-Factor

Name of HTTP request header for Duo AuthAPI factor

idp.duo.oidc.nonbrowser.header.device

X-Shibboleth-Duo-Device

Name of HTTP request header for Duo AuthAPI device ID or name

idp.duo.oidc.nonbrowser.header.passcode

X-Shibboleth-Duo-Passcode

Name of HTTP request header for Duo AuthAPI passcode

idp.duo.oidc.nonbrowser.auto

true

Allow the factor to be defaulted in as "auto" if no headers are received

idp.duo.oidc.nonbrowser.apiHost

${idp.duo.oidc.apiHost}

Duo AuthAPI hostname assigned to the integration

idp.duo.oidc.nonbrowser.integrationKey

Duo AuthAPI integration key (supplied by Duo)

idp.duo.oidc.nonbrowser.secretKey

Duo AuthAPI secret key (supplied by Duo)clientAddressTrusted

true

Pass client address to Duo in API calls to support logging, push display, and network-based Duo policies

idp.authn.DuoOIDC.addDefaultPrincipals 1.3.0

true

If set to false this will prevent the addition of the default principals even if a ContextToPrincipalMappingStrategy is not set. Previous to 1.3.0 if the ContextToPrincipalMappingStrategy was not set, the default principals would always have been added, you can now control that by setting this to false.

idp.duo.oidc.healthcheck.nonbrowserenabled 1.header3.factor

X-Shibboleth-Duo-Factor

Name of HTTP request header for Duo AuthAPI factor0

true

Perform the Duo health check for every 2FA request? Defaults to true because this is the standard Duo workflow.

idp.duo.oidc.nonbrowseraudit.header.device

X-Shibboleth-Duo-Device

Name of HTTP request header for Duo AuthAPI device ID or name

idp.duo.oidc.nonbrowser.header.passcode

X-Shibboleth-Duo-Passcode

Name of HTTP request header for Duo AuthAPI passcodeenabled 1.3.0

false

Enable Duo audit logging.

idp.duo.oidc.audit.format 1.nonbrowser4.auto

true

Allow the factor to be defaulted in as "auto" if no headers are received0

%AAF|%a|%T|%DuoU|%DuoRedirect|%DuoCID|%DuoReqS|%DuoRespS|%DuoTXID|%DuoDID|%DuoDN|%DuoR|%DuoF

The audit format to use for audit log statements.

idp.duo.oidc.audit.category 1.nonbrowser4.clientAddressTrusted

true

Pass client address to Duo in API calls to support logging, push display, and network-based Duo policies0

Shibboleth-Audit.DuoOIDC 

The audit logging category to use

Expand
titleProperties (Nimbus)

The below table are properties that only apply to the Shibboleth Nimbus plugin:

Name

Default

Description

idp.duo.oidc.connectionTimeout

defaults to the global HttpClient options in services.properties (PT1M)

Maximum length of time to wait for the connection to be established

idp.duo.oidc.connectionRequestTimeout

defaults to the global HttpClient options in services.properties (PT1M)

Maximum length of time to wait for a connection to be returned from the connection manager

idp.duo.oidc.socketTimeout

defaults to the global HttpClient options in services.properties (PT1M)

Maximum period inactivity between two consecutive data packets

idp.duo.oidc.maxConnectionsTotal

defaults to the global HttpClient options in services.properties (100)

Max total simultaneous connections allowed by the pooling connection manager

idp.duo.oidc.maxConnectionsPerRoute

defaults to the global HttpClient options in services.properties (100)

Max simultaneous connections per route allowed by the pooling connection manager

idp.duo.oidc.nimbus.checkRevocation

false

To enable certificate revocation checking. See Certificate Revocation Checking

Expand
titleProperties (General)

The general properties configuring this flow via authn/authn.properties are:

Name

Default

Description

idp.authn.DuoOIDC.order

1000

Flow priority relative to other enabled login flows (lower is "higher" in priority)

idp.authn.DuoOIDC.nonBrowserSupported

false

Whether the flow should handle non-browser request profiles (e.g., ECP)

idp.authn.DuoOIDC.passiveAuthenticationSupported

false

Whether the flow allows for passive authentication

idp.authn.DuoOIDC.forcedAuthenticationSupported

true

Whether the flow supports forced authentication

idp.authn.DuoOIDC.proxyRestrictionsEnforced

%{idp.authn.enforceProxyRestrictions:true}

Whether the flow enforces upstream IdP-imposed restrictions on proxying

idp.authn.DuoOIDC.proxyScopingEnforced

false

Whether the flow considers itself to be proxying, and therefore enforces SP-signaled restrictions on proxying

idp.authn.DuoOIDC.discoveryRequired

false

Whether to invoke IdP-discovery prior to running flow

idp.authn.DuoOIDC.lifetime

%{idp.authn.defaultLifetime:PT1H}

Lifetime of results produced by this flow

idp.authn.DuoOIDC.inactivityTimeout

%{idp.authn.defaultTimeout:PT30M}

Inactivity timeout of results produced by this flow

idp.authn.DuoOIDC.reuseCondition

shibboleth.Conditions.TRUE

Bean ID of Predicate<ProfileRequestContext> controlling result reuse for SSO

idp.authn.DuoOIDC.activationCondition

shibboleth.Conditions.TRUE

Bean ID of Predicate<ProfileRequestContext> determining whether flow is usable for request

idp.authn.DuoOIDC.subjectDecorator


Bean ID of BiConsumer<ProfileRequestContext,Subject> for subject customization

idp.authn.DuoOIDC.supportedPrincipals

(see below)

Comma-delimited list of protocol-specific Principal strings associated with flow

idp.authn.DuoOIDC.addDefaultPrincipals 1.3.0

falsetrue

Whether to auto-attach the preceding set of Principal objects to each Subject produced by this flow

As a non-password based flow, the supportedPrincipals property defaults to the following XML: 

Code Block
languagexml
<list>
  <bean parent="shibboleth.SAML2AuthnContextClassRef"c:classRef="http://example.org/ac/classes/mfa" />
  <bean parent="shibboleth.SAML1AuthenticationMethod"c:method="http://example.org/ac/classes/mfa" />
</list>

In property form, this is expressed as:

idp.authn.DuoOIDC.supportedPrincipals = saml2/http://example.org/ac/classes/mfa, saml1/http://example.org/ac/classes/mfa

However, this default is (obviously) intended purely as an illustrative example of how to define your own values, as there are no standard ones to use.

Expand
titleFlow Descriptor XML

To replace the internally defined flow descriptor bean, the following XML is required:

Code Block
languagexml
<util:list id="shibboleth.AvailableAuthenticationFlows">
 
    <bean p:id="authn/DuoOIDC" parent="shibboleth.AuthenticationFlow"
            p:order="%{idp.authn.DuoOIDC.order:1000}"
            p:nonBrowserSupported="%{idp.authn.DuoOIDC.nonBrowserSupported:false}"
            p:passiveAuthenticationSupported="%{idp.authn.DuoOIDC.passiveAuthenticationSupported:false}"
            p:forcedAuthenticationSupported="%{idp.authn.DuoOIDC.forcedAuthenticationSupported:true}"
            p:proxyRestrictionsEnforced="%{idp.authn.DuoOIDC.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
            p:proxyScopingEnforced="%{idp.authn.DuoOIDC.proxyScopingEnforced:false}"
            p:discoveryRequired="%{idp.authn.DuoOIDC.discoveryRequired:false}"
            p:lifetime="%{idp.authn.DuoOIDC.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
            p:inactivityTimeout="%{idp.authn.DuoOIDC.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
            p:reuseCondition-ref="#{'%{idp.authn.DuoOIDC.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
            p:activationCondition-ref="#{'%{idp.authn.DuoOIDC.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
            p:subjectDecorator-ref="#{getObject('%{idp.authn.DuoOIDC.subjectDecorator:}'.trim())}">
        <property name="supportedPrincipalsByString">
            <bean parent="shibboleth.CommaDelimStringArray"
                c:_0="#{'%{idp.authn.DuoOIDC.supportedPrincipals:}'.trim()}" />
        </property>
    </bean>
 
</util:list>

In older versions and upgraded systems, this list is defined in conf/authn/general-authn.xml. In V4.1+, no default version of the list is provided and it may simply be placed in conf/global.xml if needed.

...