Current File(s): conf/oidc.properties, conf/authn/oauth2client-authn-config.xml
Format: Native Spring

Overview

The authn/OAuth2Client login flow supports an extensible set of back-ends and is designed to handle all of the supported OAuth client authentication types.

Like the IdP itself, this flow supports the CredentialValidator interface and the chaining of CredentialValidator plugins in arbitrary sequences.

General Configuration

Most features of this flow can be configured with conf/oidc.properties. Some advanced features require Spring configuration, and the file conf/authn/oauth2client-authn-config.xml will be imported if it is created and populated, and supports definitions of beans into the proper Spring flow context. It is analagous to conf/authn/password-authn-config.xml from the IdP proper.

All of the CredentialValidator types supported by the IdP are supported here (the links here are to the implementation class' Javadoc rather than the IdP documentation). There are two additional validators provided and wired in as the default configuration to provide backward compatibility supporting both client secrets resolved from metadata and signed JWT authentication. The compatibility validators generally don’t require any special configuration. The main reason for customizing the chain of validators is to add validation of client secrets against other back-ends (e.g., using LDAP to validate “service accounts” issued to clients).

With the exception of LDAP, the other beans above are not pre-configured with special beans or properties to control their behavior as they are in the IdP’s own configuration. As a result you would need to directly inherit from and confgure these beans appropriately to use them.

In the case of LDAP, a default shibboleth.LDAPAuthenticationFactory bean is installed as in the Password flow, and supports a similar set of properties as documented on the LDAPAuthnConfguration page, but apart from the pooling properties that are reused from the original configuration, the others are renamed to insert “OAuth2Client” into the property names to enable separation of the search location and any other settings that need to be unique. For example, the documented property named “idp.authn.LDAP.ldapURL” is named “idp.authn.OAuth2Client.LDAP.ldapURL” for this use case.

Aside from the more specific back-end configurations, there are beans and properties defined for some general configuration independent of the back-end chosen. They are all listed in the reference section below.

The most important bean is shibboleth.authn.OAuth2Client.Validators, a List of CredentialValidator plugins that should be used to perform the authentication processing.

A property named idp.authn.OAuth2Client.requireAll controls whether the credentials must be validated successfully by all applicable plugins in the list, or just one.

Combining plugins tends to be more complex but the default, requiring only a single valid result, is fairly simple to deal with. One obvious issue is that you should make sure to set the property named idp.authn.OAuth2Client.removeAfterValidation to false if you apply the "require all" mode to prevent the client information from being pulled mid-request.

Basic Features

There are parent beans defined for each back-end plugin supported to allow easy incorporation of the default configured behavior into the chain of validators.

For example, this syntax defines a single LDAP validator that uses settings defined in a manner consistent with older versions of the software. The parent bean is used "as is" with no changes, and most of the confguration would be handled via properties (using the renamed versions noted above).

<util:list id="shibboleth.authn.OAuth2Client.Validators">
    <ref bean="shibboleth.LDAPValidator" />
</util:list>

This syntax in contrast adds support for LDAP alongside the original two built-in options so they remain supported for some clients:

<util:list id="shibboleth.authn.OAuth2Client.Validators">
    <ref bean="shibboleth.OIDCClientInfoValidator" />
    <ref bean="shibboleth.JWTValidator" />
    <ref bean="shibboleth.LDAPValidator" />
</util:list>

As with user authentication, it is possible to apply normalization or matching rules to the “client_id” supplied by the OAuth client. From an OAuth perspective, the client_id is still officially whatever the client uses, but this can be separated from the manner in which authentication happens, on a per-validator basis.

Unlike with user authentication, there are no global transform or matching settings defined, but each validator individually supports them as defined in the javadocs. For example (in conf/authn/oauth2client-authn-config.xml):

<util:list id="shibboleth.authn.OAuth2Client.Validators">
    <ref bean="shibboleth.OIDCClientInfoValidator" />
    <ref bean="shibboleth.JWTValidator" />
    <bean parent="shibboleth.LDAPValidator" p:matchExpression="^\S+\.\d+$" />
</util:list>

While in some cases it may be acceptable to reuse the existing post-login subject canonicalization configuration used for username handling, it is expected that this may not work for most deployments. You may set the property idp.authn.OAuth2Client.c14n.postLoginFlows to an alternate bean ID referencing a list defined in conf/c14n/subject-c14n.xml that defines the c14n flow(s) to run separately from the built-in list. In many cases, an example bean such as this may suffice:

    <!-- Separate list of flows to apply to OAuth2 client authentication. -->
    <util:list id="custom.OAuth2Client.PostLoginSubjectCanonicalizationFlows">
        <ref bean="c14n/simple" />
    </util:list>

The shibboleth.OIDCClientInfoValidator validator bean that supports client secrets resolved from metadata supports hashed secrets. If a secret value is prefixed by “{SHA2}”, then the supplied secret is hashed (with SHA-256) and base64-encoded before comparing it to the rest of the secret string. This is an unsalted hash so is not really suitable for exposing to offline attacks but is at least obsfuscated. This is automatic so no configuration is required.

Advanced Features

While somewhat less interesting than for user authentication, account lockout is supported in parallel with it for this use case.

A pluggable implementation of account lockout can be enabled by defining a bean called shibboleth.authn.OAuth2Client.AccountLockoutManager that implements the AccountLockoutManager interface. For other details, refer to the original PasswordAuthnConfiguration material on this feature (only the bean name is different).

Creating a new back-end relies on supplying new implementations of the CredentialValidator interface, usually by inheriting from the net.shibboleth.idp.authn.AbstractUsernamePasswordCredentialValidator class. This is again identical to the original IdP support for this capability and the same implementation can be used for either user or client authenticatio if desired.

Reference

The beans defined for use in authn/oauth2client-authn-config.xml follow:

Bean ID

Default

Description

shibboleth.authn.OAuth2Client.Validators

List<CredentialValidator>

Chain of OIDCClientInfo and JWT Validators.

Defines the set of validator plugins to use

shibboleth.OIDCClientInfoValidator

OIDCClientInfoCredentialValidator

Bean implementing client metadata validation of client secrets

shibboleth.JWTValidator

JWTCredentialValidator

Bean implementing signed JWT authentication

shibboleth.LDAPValidator

LDAPCredentialValidator


Parent bean for defining LDAP validation

shibboleth.KerberosValidator

KerberosCredentialValidator


Parent bean for referencing or defining Kerberos validation

shibboleth.JAASValidator

JAASCredentialValidator


Parent bean for referencing or defining JAAS validation

shibboleth.HTPasswdValidator

HTPasswdCredentialValidator


Parent bean for referencing or defining htpasswd file validation

shibboleth.StorageBackedAccountLockoutManager

StorageBackedAccountLockoutManager


Parent bean for declaring storage-backed account lockout with appropriate defaults

shibboleth.authn.OAuth2Client.AccountLockoutManager

AccountLockoutManager


A lockout manager that, if defined, will enable account lockout feature

shibboleth.authn.OAuth2Client.ClassifiedMessageMap

Map<String,List<String>>

A map between defined error/warning conditions and events and implementation-specific message fragments to map to them. This is less relevant for machine-to-machine authentication but may be used to help with error signaling.

The flow-specific properties usable via oidc.properties are:

Property

Default

Description

idp.authn.OAuth2Client.requireAll

false

Whether all validators must succeed or just one

idp.authn.OAuth2Client.removeAfterValidation

true

Whether to remove the object holding the password from the request's active state after validating it (to avoid it being preserved in the session any longer than needed)

idp.authn.OAuth2Client.retainAsPrivateCredential

false

Whether to keep the password around as a private "credential" in the Java Subject for use in later stages such as attribute resolution

idp.authn.OAuth2Client.c14n.postLoginFlows

shibboleth.PostLoginSubjectCanonicalizationFlows

Bean ID of list of subject c14n flow beans used, to allow separation from standard user authentication

The general properties configuring this flow via oidc.properties are below. Many of the usual settings applicable to user authentication are hardwired due to the specialized nature of this flow for OAuth client use.

Property

Default

Description

idp.authn.OAuth2Client.order

1000

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

idp.authn.OAuth2Client.activationCondition

shibboleth.Conditions.TRUE

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

idp.authn.OAuth2Client.subjectDecorator


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

idp.authn.OAuth2Client.supportedPrincipals

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

idp.authn.OAuth2Client.addDefaultPrincipals

true

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

To replace the internally defined flow descriptor bean, the following XML is required (the same list normally used for user authentication).

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

Notes

The idp.authn.OAuth2Client.retainAsPrivateCredential property should be used with caution, as it retains the password and makes it available in plaintext form within server memory at various stages.