Configure Step-up Authentication for Web Apps

With step-up authentication, applications that allow access to different types of resources can require users to authenticate with a stronger mechanism to access sensitive information or perform certain transactions.

For instance, a user may be allowed to access views with sensitive data or reset their password only after confirming their identity using multi-factor authentication (MFA).

To accomplish step-up authentication for your web app, you will create an Action that challenges the user to authenticate with MFA when the web app asks for it, check the ID Token claims for MFA if the user tries to access a restricted page, and then challenge the user if MFA is not included in the claim.

Validate ID tokens for MFA

When a user logs in, you get an ID token that contains information relevant to the user's session in the form of claims. The relevant claim is amr (authentication methods reference) which is a JSON array of strings that indicates the authentication method used during login. It must be present in the ID token's payload and must contain the value mfa.

Its values may include any of the pre-defined Authentication Method Reference Values. Because it can contain claims other than mfa, when validating you must both test for its existence and examine its contents for a value of mfa.

If a user attempts to access a restricted page and the token shows that the user has not authenticated with MFA, then you can retrigger authentication, which you have configured to trigger MFA using an Action. Once the user provides the second factor, a new ID token that contains the amr claim is generated and sent to the app.

  1. Get the ID token.

  2. Verify the token's signature, which is used to verify that the sender of the token is who it says it is and to ensure that the message wasn't changed along the way.

  3. Validate the following claims:

    Claim Description
    exp Token expiration
    iss Token issuer
    aud Intended recipient of the token
    amr If amr does not exist in the payload or does not contain the value mfa, the user did not log in with MFA. If amr exists in the payload and contains the value mfa, then the user did log in with MFA.

AMR claim exceptions

The amr claim is required except in the following use cases:

  1. In hosted login flows, only after the user successfully passes an MFA challenge, the amr claim is injected into the ID token. If the app uses silent authentication or Refresh Tokens for newly issued ID tokens, the amr claim will not be present because the user previously completed login with MFA.

  2. MFA API issued tokens do not contain the amr claim. The amr claim flags the authentication methods used when the user receives the ID Token. In the MFA API authentication process, the application controls the authentication flow and can enforce MFA as needed.

In the examples below, you can compare the potential values included in an ID token's payload when a user has authenticated with MFA versus when they have not.

Example: Values with MFA

to configure this snippet with your account
{
    "iss": "https://{yourDomain}/",
    "sub": "auth0|1a2b3c4d5e6f7g8h9i",
    "aud": "{yourClientId}",
    "iat": 1522838054,
    "exp": 1522874054,
    "acr": "http://schemas.openid.net/pape/policies/2007/06/multi-factor",
    "amr": [
        "mfa"
    ]
}

Was this helpful?

/

Example: Values without MFA

{
    "iss": "https://{yourDomain}/",
    "sub": "auth0|1a2b3c4d5e6f7g8h9i",
    "aud": "{yourClientId}",
    "iat": 1522838054,
    "exp": 1522874054
}

Was this helpful?

/

Scenario: Salary data with push notifications

In the following scenario, a web app authenticates a user with a username and password. Some users want to access a specific screen that displays salary data, so they must authenticate with Guardian push factor.

Prerequisites

For this scenario, you must configure the following items in the Dashboard:

Create an Action

Create an Action that challenges the user to authenticate with MFA when the web app requests it. Go to Dashboard > Actions > Flows, and create an Action that contains the following content:

exports.onExecutePostLogin = async (event, api) => {
  const CLIENTS_WITH_MFA = ['REPLACE_WITH_YOUR_CLIENT_ID'];
  // run only for the specified clients
  if (CLIENTS_WITH_MFA.includes(event.client.client_id)) {
    // ask for MFA only if the web app said so in the authentication request
    if (event.transaction.acr_values === 'http://schemas.openid.net/pape/policies/2007/06/multi-factor') {
      api.multifactor.enable('any', { allowRememberBrowser: false });
    }
  }
}

Was this helpful?

/

  • The CLIENTS_WITH_MFA variable contains the client IDs of the applications you want this Action to apply to. You can remove this (and the if conditional that follows) if you don't need it.

  • The context.request.query.acr_values property contains the context class that the Authorization Server is being requested to use when processing requests from the application. It only exists when the application includes it in the authentication request. In this example, our web app will include it in the authentication request, but only when a user who has not already authenticated with MFA tries to access salary information. When our web app includes it, it will set a value of http://schemas.openid.net/pape/policies/2007/06/multi-factor, which indicates that we want the Authorization Server to require MFA, and the context.multifactor property value that we set in our code will specify MFA via push notification.

Configure app

Configure the app to check that the user has authenticated using MFA when a user tries to access the restricted salary information page. (When a user has authenticated with MFA, the ID token claims contain the amr claim with a value of mfa.) If the user has already authenticated with MFA, then the web app will display the restricted page; otherwise, the web app will send a new authentication request that includes the acr_values parameter with a value of: http://schemas.openid.net/pape/policies/2007/06/multi-factor which will trigger the Action.

The web app in this scenario uses the Authorization Code Flow to authenticate, so the request is as follows:

https://{yourDomain}/authorize?
        audience=https://{yourDomain}/userinfo&
        scope=openid&
        response_type=code&
        client_id={yourClientId}&
        redirect_uri={https://yourApp/callback}&
        state={yourOpaqueValue}&
        acr_values=http://schemas.openid.net/pape/policies/2007/06/multi-factor

Was this helpful?

/

Once the user authenticates with MFA, the web app receives the authorization code, which must be exchanged for the new ID token, which should now contain the amr claim with a value of mfa. To learn how to exchange the code for an ID token, read Add Login Using the Authorization Code Flow.

Validate ID token

In this scenario, perform the validations using the JSON Web Token Sample Code, which verifies the token's signature (jwt.verify), decodes the token, checks whether the payload contains amr, and if so, logs the results in the console.

const AUTH0_CLIENT_SECRET = '{yourClientSecret}';
const jwt = require('jsonwebtoken');

jwt.verify(id_token, AUTH0_CLIENT_SECRET, { algorithms: ['HS256'] }, function(err, decoded) {
  if (err) {
    console.log('invalid token');
    return;
  }

  if (Array.isArray(decoded.amr) && decoded.amr.indexOf('mfa') >= 0) {
    console.log('You used mfa');
    return;
  }

  console.log('you are not using mfa');
});

Was this helpful?

/

Learn more