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 a rule 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 a rule. 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.

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://YOUR_DOMAIN/",
    "sub": "auth0|1a2b3c4d5e6f7g8h9i",
    "aud": "YOUR_CLIENT_ID",
    "iat": 1522838054,
    "exp": 1522874054,
    "acr": "http://schemas.openid.net/pape/policies/2007/06/multi-factor",
    "amr": [
        "mfa"
    ]
}


Example: Values without MFA

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

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 rule

Create a rule that challenges the user to authenticate with MFA when the web app requests it. Go to Dashboard > Auth Pipeline > Rules, and create a rule that contains the following content:

    function(user, context, callback) {

      var CLIENTS_WITH_MFA = ['YOUR_CLIENT_ID'];
      // run only for the specified clients
      if (CLIENTS_WITH_MFA.indexOf(context.clientID) !== -1) {
        // ask for MFA only if the web app said so in the authentication request
        if (context.request.query.acr_values === 'http://schemas.openid.net/pape/policies/2007/06/multi-factor'){
          context.multifactor = {
            provider: 'any',
            allowRememberBrowser: false
          };
        }
      }

      callback(null, user, context);
    }

    

  • The CLIENTS_WITH_MFA variable holds the Client IDs of all the applications you want to use this rule. (You can remove this (and the if statement 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 ith 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 acces 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 our rule.

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

    https://YOUR_DOMAIN/authorize?
        audience=https://YOUR_DOMAIN/userinfo&
        scope=openid&
        response_type=code&
        client_id=YOUR_CLIENT_ID&
        redirect_uri=https://YOUR_APP/callback&
        state=YOUR_OPAQUE_VALUE&
        acr_values=http://schemas.openid.net/pape/policies/2007/06/multi-factor

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 = 'YOUR_CLIENT_SECRET';
    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');
    });

    

Learn more