Rate this page

Multi-factor authentication

As we’ve seen, a Data Governance Broker client makes an OpenID Connect request to authenticate a user. If the user isn’t already logged in to the Data Governance Broker, then it will prompt the user to log in and perhaps authorize the request before returning a response to the client. If the user is already logged in, then a response will be returned directly to the client. In either case, the client receives an ID token with claims about the user’s authentication state.

Depending on the Data Governance Broker’s configuration and policies, the login process might involve multiple authentication factors. For example, the user might be prompted to enter a username and password, followed by a prompt to enter a time-based one-time password using an app like Google Authenticator or Authy. The Data Governance Broker’s authentication configuration could also vary the authentication process so that, for example, the user must provide a username and password every 12 hours but must provide a time-based one-time password every 6 hours.

When a user authenticates, the Data Governance Broker’s policy engine is passed the user’s authentication context, consisting of information such as the user’s client IP address, the time, the request headers, the authentication method used, the time since the last authentication event, and so on. The Data Governance Broker applies this authentication context against its authentication context class references (ACRs), groupings of configuration and policy requirements. When an ACR is found that is satisfied by the current authentication context, the Data Governance Broker sets the ACR as the value of the ID token’s acr claim, if an ID token was requested.

By default, this processing occurs without the client’s intervention. However, an application can specify that particular ACRs be satisfied during an authentication request. If certain ACRs are configured to require multi-factor authentication, an application can thereby require that a user log in using multi-factor authentication.

Requesting specific ACRs

When an application makes an OpenID Connect request to authenticate a user, it has the option of specifying a list of ACRs that it requires to be satisfied, in order of preference. The application will receive a failure response if no ACR in its list is satisfied by the user’s authentication state.

The application’s list of preferred ACRs can be declared in two different ways, with the following order of priority:

  1. Via an acr_values request parameter to the OpenID Connect request.
  2. Via the application’s configuration, in its Permitted ACRs property.
  3. Not at all, in which case the Data Governance Broker determines which ACRs must be satisfied. This is set by the Default ACR property of the OpenID Connect Service configuration.

To take a simple example, assume that an ACR exists called MFA. This ACR requires that the user log in using both username/password and a second factor. If a client submits an OpenID Connect request including acr_values=MFA, and the user does not provide a second factor during login, then the authentication request will fail.

The following authentication request URI declares that the authentication must satisfy the ‘MFA’ ACR:


And the following authentication response shows that the ACR could not be satisfied because the user has not enabled multi-factor authentication:


The acr ID token claim

An application might also check that a particular ACR was satisfied after an authentication has occurred. It does this by looking at the acr claim of the ID token. This can be useful when an application has already authenticated a user at the default level but wants to determine if it needs to step up the user’s authentication before performing a task requiring a high level of security.

Here’s a Java example that checks the acr claim using the Nimbus JOSE+JWT library.

SignedJWT idToken = SignedJWT.parse("eyJraWQiOi...");

// Signature verification omitted...

JWTClaimsSet claims = idToken.getJWTClaimsSet();

// Other claim checks omitted...

if (claims.getStringClaim("acr").equals("MFA")) {
  System.out.println("ACR satisfied, proceeding...");
} else {
  System.out.println("ACR not satisfied, stepping up authentication...");
  // Build OpenID Connect URI with 'acr_values' and 'prompt' parameters.
  URI authenticationUri = UriBuilder.fromUri(config.getBaseUri())
      .queryParam("response_type", "code")
      .queryParam("client_id", config.getClientId())
      .queryParam("redirect_uri", config.getRedirectUri())
      .queryParam("state", stateJwt)
      .queryParam("nonce", nonce)
      .queryParam("scope", config.getScopes().stream().collect(Collectors.joining(" ")))
      .queryParam("acr_values", "MFA")
      .queryParam("prompt", "login")