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.
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.
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 valuemfa
, the user did not log in with MFA. Ifamr
exists in the payload and contains the valuemfa
, then the user did log in with MFA.
AMR claim exceptions
The amr
claim is required except in the following use cases:
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, theamr
claim will not be present because the user previously completed login with MFA.MFA API issued tokens do not contain the
amr
claim. Theamr
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:
Enable MFA to use push notifications.
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 = ['{yourClientId}'];
// 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);
}
Was this helpful?
The
CLIENTS_WITH_MFA
variable holds the Client IDs of all the applications you want to use this rule. (You can remove this (and theif
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 with MFA tries to access salary information. When our web app includes it, it will set a value ofhttp://schemas.openid.net/pape/policies/2007/06/multi-factor
, which indicates that we want the Authorization Server to require MFA, and thecontext.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://{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?