On this page
Step-up authentication using ACR values
This guide explains how to include the acr_values
parameter in your authorization requests to increase the level of end user assurance.
Learning outcomes
- Know the purpose of the
acr_values
parameter. - Learn about the different types of
acr_values
that are supported out of the box. - Use an
acr_values
parameter in your authorization request.
What you need
- Okta Developer Edition organization (opens new window)
- An app that you want to configure
acr_values
for. You can create an app integration using AIW (opens new window) or use an existing one.
Overview
Users want seamless access to certain resources, but organizations want to increase the user’s level of assurance before they access anything sensitive. It’s difficult to strike a balance between implementing stronger security controls and offering a frictionless experience for your users to easily interact with the app. Using the acr_values
parameter provides easy access to one layer of resources and secure access to another layer of resources.
The acr_values
parameter refers to authentication context class reference. Each value defines a specific set of assurance level requirements that the protected resource requires from the authentication event associated with the access and ID tokens.
Today an authorization server relies on authentication policies (opens new window) to authenticate the user. After the user is authenticated, the authorization server evaluates the scopes and the grant types defined for the app, and then issues the tokens. Although this approach works in many situations, there are several circumstances where more is needed. Resource servers (your protected APIs) can require different authentication strengths or elapsed time frames for different use cases. For example, an ecommerce app requires different authentication strengths depending on whether the item being purchased exceeds a certain threshold. Another example is an app that requires a higher level of assurance before making changes to sensitive information.
Okta has created predefined acr_values
that are described in the Predefined parameter values section. You can include one of these values, based on your use case, in the client authorization request to request a different authentication assurance. The authorization server returns an access token and/or an ID token that contains the acr
claim. This claim conveys information about the level of assurance that the user verified at the time of authentication. The resource server can then validate these parameters to ensure that the user verified the required level of assurance.
Note: You can specify a
max_age
parameter value to require an elapsed time frame. Also, if you want to ignore the existing session and reauthenticate the user each time, passmax_age=0
in the request. For Classic Engine, passmax_age=1
. See the Request parameters table (opens new window) for the/authorize
endpoint for more information onmax_age
.
The Okta redirect and embedded deployment models support the use of the acr_values
parameter. The parameter works with any OpenID Connect (OIDC) app, such as web, native, or SPA, and both the org authorization server and custom authorization servers support it.
Evaluation flow
In Identity Engine, assurances from policies are always evaluated in order of factor verification, constraints, and re-authentication. The global session policy is evaluated first, then the authentication policy, and then the acr_values
parameter in the request. The authentication policy is always evaluated before the acr_values
parameter.
In Classic Engine when a user doesn't have a session, the more restrictive policy is evaluated first, such as the Okta sign-on policy or the app sign-on policy. Also, if an assurance requirement is more restrictive, such as an acr_values
parameter, that's evaluated first. The second most restrictive policy or assurance requirement is then evaluated and so on. When a user already has a session, the app sign-on policy is always evaluated first. Then, the acr_values
parameter in the request.
In both Identity Engine and Classic Engine, if the user has a session, the previously satisfied authenticators are considered before prompting for factors that the acr_values
parameter requires in the request. Also, if the user is unable to satisfy the level of assurance, Okta returns an error (opens new window) (error=unmet_authentication_requirements
) to the callback endpoint.
Factor enrollment
If the user hasn't enrolled a factor, during step-up authentication the user is prompted to enroll a factor as long as an authenticator enrollment policy (opens new window) is configured (or the Multifactor Enrollment Policy (opens new window) in Classic Engine).
Predefined parameter values
The following predefined optional parameters are available for use in your authorization requests:
Note: Any unsupported
acr_values
sent in the authorize request are ignored.
Parameter value for acr_values | Description | Parameter Type | DataType |
---|---|---|---|
urn:okta:loa:1fa:any | Any one factor. Allows one factor authentication with no requirements on which factor. | Query | String |
urn:okta:loa:1fa:pwd | Password only. Allows one factor authentication that requires the user’s password. | Query | String |
urn:okta:loa:2fa:any | Any two factors. Allows two factor authentication with no requirements on which factors. | Query | String |
urn:okta:loa:2fa:any:ifpossible Identity Engine | Any two factors if possible. Allows two factor authentication with no requirements on which factors. Any two factors are presented only if the user is enrolled, otherwise any one factor is presented. | Query | String |
phr Identity Engine | Phishing-Resistant. Requires users to provide possession factors that cryptographically verify the sign-in server (the origin). Currently, only FIDO2/WebAuthn satisfies this requirement. Because phishing resistance implies device binding (opens new window), that constraint is selected automatically when phr is specified. | Query | String |
phrh Identity Engine | Phishing-Resistant Hardware-Protected. Requires that you store keys being used to authenticate in secure hardware (TPM, Secure Enclave) on the device. Currently, only Okta Verify meets this constraint. Because hardware protection implies device binding (opens new window), that constraint is selected automatically when phrh is specified. | Query | String |
Authentication flow using ACR values
At a high-level, this flow has the following steps:
Per your use case, include the
acr_values
predefined parameter value in the authentication request.The authentication scenarios required by the grant type authenticate the user in accordance with the predefined
acr_values
parameter value used in the authentication request.When the authentication flow completes, the authorization server returns an access token and/or an ID token to the client that contains the
acr
claim.The client requests access to the protected resource and presents the new access token.
The resource server evaluates the assurance level of the access token against its requirements and then returns the protected resource.
Add the parameter value to the auth request
The following is an example authorization request using the urn:okta:loa:1fa:any
predefined acr_values
parameter value. In this example, the Authorization Code grant type is used.
Request
https://{yourOktaDomain}/oauth2/default/v1/authorize?client_id={clientId}
&response_type=code
&scope=openid
&redirect_uri=https://{yourOktaDomain}/authorization-code/callback
&state=296bc9a0-a2a2-4a57-be1a-d0e2fd9bb601
&acr_values=urn:okta:loa:1fa:any
The authorization code is returned in the response. And then the request is made to the /token
endpoint to exchange the authorization code for an ID token and an access token. See the Authorization Code grant type for a diagram of this flow.
Response
The tokens are truncated for brevity.
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJraW…..vSqrH1Q",
"scope": "openid",
"id_token": "eyJraW…..WlB8Y9pQ"
}
To check the returned ID token payload, copy the values and paste them into any JWT decoder (for example: https://jwt.io/
). Using a JWT decoder, confirm that the token contains the acr
claim.
ID token
{
"sub": "00u47ijy7sRLaeSdC0g7",
"ver": 1,
"iss": "https://{yourOktaDomain}/oauth2/default",
"aud": "0oa48e74ox4t7mQJX0g7",
"iat": 1661289624,
"exp": 1661293224,
"jti": "ID.dz6ibX-YnBNlt14huAtBULam_Z0_wPG0ig5SWCy8XQU",
"amr": [
"pwd"
],
"acr": "urn:okta:loa:1fa:any",
"idp": "00o47ijbqfgnq5gj00g7",
"auth_time": 1661289603,
"at_hash": "w6BLQV3642TKWvaVwTAJuw"
}
Access token
{
"ver": 1,
"jti": "AT.NovJtQ_NrJ6cgy3h1-638ArovwYXWslu0teQ2M3Ux9c",
"iss": "https://{yourOktaDomain}/oauth2/default",
"aud": "api://default",
"iat": 1661289624,
"exp": 1661293224,
"acr": "urn:okta:loa:1fa:any",
"cid": "0oa48e74ox4t7mQJX0g7",
"uid": "00u47ijy7sRLaeSdC0g7",
"scp": [
"openid"
],
"auth_time": 1661289603,
"sub": "joe.smith@example.com"
}
Refresh token behavior
When you use the refresh token to refresh access and ID tokens, the tokens reflect the acr_values
parameter value sent in the original authentication request. Use the auth_time
parameter value (opens new window) to validate when the original authentication occurred.
Next steps
Read more about Okta access tokens in the OIDC & OAuth 2.0 API Reference (opens new window).
Read more about policies on the Policies concept page.
Read more about OAuth 2.0 and OIDC in the OAuth 2.0 and OpenID Connect overview.