Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,25 @@ This guide explains how to include the `acr_values` parameter in your authorizat
**What you need**

* [Okta Developer Edition organization](https://developer.okta.com/signup)
* An application that you want to configure `acr_values` for. You can [create a new app integration using AIW](https://help.okta.com/okta_help.htm?id=ext_Apps_App_Integration_Wizard) or use an existing one.
* Existing OpenID Connect (OIDC) or SAML app integration that you want to configure `acr_values` for. See <StackSnippet snippet="createapp" inline />

---

## 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 application. 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.
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 <StackSnippet snippet="assertion" inline />.

Today an authorization server relies on [authentication policies](/docs/reference/api/policy/#authentication-policy) to authenticate the user. After the user is authenticated, the authorization server evaluates the scopes and the grant types defined for the application, 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 application requires different authentication strengths depending on whether the item being purchased exceeds a certain threshold. Another example is an application that requires a higher level of assurance before making changes to sensitive information.
<StackSnippet snippet="overview" /><br>

Okta has created predefined `acr_values` that are described in the [Predefined parameter values](#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. Additionally, if you want to ignore the existing session and reauthenticate the user each time, pass `max_age=0` in the request. For Classic Engine, pass `max_age=1`. See the [Request parameters table](/docs/reference/api/oidc/#request-parameters) for the `/authorize` endpoint for more information on `max_age`.

Okta's [redirect and embedded](/docs/concepts/redirect-vs-embedded/) deployment models support the use of the `acr_values` parameter. The parameter works with any OpenID Connect application, such as web, native, or SPA, and it’s supported by both the [org authorization server and custom authorization servers](/docs/concepts/auth-servers/).
Okta's [redirect and embedded](/docs/concepts/redirect-vs-embedded/) deployment models support the use of the `acr_values` parameter. <StackSnippet snippet="parameter" inline />.

### Evaluation flow

In Okta Identity Engine, assurances from policies are always evaluated in order of factor verification, constraints, and re-authentication. The [global session policy](/docs/concepts/policies/#sign-on-policies) 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 Okta 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 application sign-on policy. Additionally, if an assurance requirement is more restrictive, such as an `acr_values` parameter, that is evaluated first. The second most restrictive policy or assurance requirement is then evaluated and so on. When a user already has a session, the application 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 are required by the `acr_values` parameter in the request. Additionally, if the user is unable to satisfy the level of assurance, Okta returns an [error](https://openid.net/specs/openid-connect-unmet-authentication-requirements-1_0.html) (`error=unmet_authentication_requirements`) to the callback endpoint.
<StackSnippet snippet="evalflowclassic" /><br>

### Factor enrollment

Expand All @@ -64,102 +58,17 @@ The following predefined optional parameters are available for use in your autho

## Authentication flow using ACR values

<div class="three-quarter">

![Flow diagram that displays the back and forth between the client, resource server, and the authorization server](/img/auth/step-up-authentication-acr-flow.png)

</div>

At a high-level, this flow has the following steps:

1. Per your use case, include the `acr_values` predefined parameter value in the authentication request.

2. The authentication scenarios required by the [grant type](/docs/guides/implement-grant-type/authcode/main/) authenticate the user in accordance with the predefined `acr_values` parameter value used in the authentication request.

3. 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.

4. The client requests access to the protected resource and presents the new access token.

5. The resource server evaluates the assurance level of the access token against its requirements and then returns the protected resource.
<StackSnippet snippet="diagram" /><br>

## 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](/docs/guides/implement-grant-type/authcode/main/) is used.
The following is an example authorization request using the `urn:okta:loa:1fa:any` predefined `acr_values` parameter value.

**Request**

```bash
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](/docs/guides/implement-grant-type/authcode/main/#grant-type-flow) for a diagram of this flow.
<StackSnippet snippet="addparamtorequest" /><br>

**Response**

The tokens are truncated for brevity.

```json
{
"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**

```json
{
"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**

```json
{
"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": "[email protected]"
}
```

### 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](/docs/reference/api/oidc/#request-parameters) to validate when the original authentication occurred.
<StackSnippet snippet="authresponse" />

## Next steps

Expand All @@ -168,3 +77,5 @@ When you use the refresh token to refresh access and ID tokens, the tokens refle
* Read more about policies on the [Policies](/docs/concepts/policies/) concept page.

* Read more about OpenID Connect and OAuth 2.0 in the [OAuth 2.0 and OpenID Connect overview](/docs/concepts/oauth-openid/).

* Read more about SAML 2.0 application integrations in the [Build a Single Sign-On (SSO) integration](/docs/guides/build-sso-integration/saml2/main/)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
In this example, the Authorization Code [grant type](/docs/guides/implement-grant-type/authcode/main/) is used.

**Request**

```bash
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](/docs/guides/implement-grant-type/authcode/main/#grant-type-flow) for a diagram of this flow.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
access and ID tokens
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
The tokens are truncated for brevity.

```json
{
"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**

```json
{
"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**

```json
{
"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": "[email protected]"
}
```

### 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](/docs/reference/api/oidc/#request-parameters) to validate when the original authentication occurred.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[Create OIDC app integrations](https://help.okta.com/okta_help.htm?id=ext_Apps_App_Integration_Wizard-oidc) if you don’t have an OIDC app configured.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div class="three-quarter">

![Flow diagram that displays the back and forth between the client, resource server, and the authorization server](/img/auth/step-up-authentication-acr-flow.png)

</div>

At a high level, this flow has the following steps:

1. Per your use case, include the `acr_values` predefined parameter value in the authentication request.
2. The authentication scenarios required by the [grant type](/docs/guides/implement-grant-type/authcode/main/) authenticate the user in accordance with the predefined `acr_values` parameter value used in the authentication request.
3. 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.
4. The client requests access to the protected resource and presents the new access token.
5. The resource server evaluates the assurance level of the access token against its requirements and then returns the protected resource.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
In Okta 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 application sign-on policy. Additionally, if an assurance requirement is more restrictive, such as an `acr_values` parameter, that is evaluated first. The second most restrictive policy or assurance requirement is then evaluated and so on. When a user already has a session, the application 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 are required by the `acr_values` parameter in the request. Additionally, if the user is unable to satisfy the level of assurance, Okta returns an [error](https://openid.net/specs/openid-connect-unmet-authentication-requirements-1_0.html) (`error=unmet_authentication_requirements`) to the callback endpoint.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Today an authorization server relies on [authentication policies](/docs/reference/api/policy/#authentication-policy) to authenticate the user. After the user is authenticated, the authorization server evaluates the scopes and the grant types defined for the application, 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 application requires different authentication strengths depending on whether the item being purchased exceeds a certain threshold. Another example is an application 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](#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. Additionally, if you want to ignore the existing session and reauthenticate the user each time, pass `max_age=0` in the request. For Classic Engine, pass `max_age=1`. See the [Request parameters table](/docs/reference/api/oidc/#request-parameters) for the `/authorize` endpoint for more information on `max_age`.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The parameter works with any OpenID Connect application, such as web, native, or SPA, and is supported by both the [org authorization server and custom authorization servers](/docs/concepts/auth-servers/).
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Pass the `acr_value` in the `AuthnRequest` of the SAML request as an `AuthnContextClassRef` through the `/app/{app}/{key}/sso/saml` or `/app/{app}/saml` and `/app/{app}/sso/saml` endpoints.

**Request**

```xml
<saml2p:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="TheID"
IssueInstant="2023-03-230T16:18:35Z"
Version="2.0"
AssertionConsumerServiceIndex="0"
ForceAuthn="true"/>

<saml2:Issuer>TheIssuer</saml2:Issuer>
<saml2p:NameIDPolicyFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:?"/>
<saml2p:RequestedAuthnContext>
<saml2:AuthnContextClassRef>urn:okta:loa:2fa:any</saml2:AuthnContextClassRef>
</saml2p:RequestedAuthnContext>
</saml2p:AuthnRequest>
```

The SAML assertion response contains the `AuthnContext` and includes the following:

* The `acr` value from the request passed as `AuthnContextClassRef`
* The factors (Authentication Method Reference (AMR) claims) used to authenticate the user passed as a list of `AuthnContextDecl`
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SAML assertion
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
```xml
<saml2:AuthnStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
AuthnInstant="2023-03-24T22:14:53.964Z"
SessionIndex="id1679696095926.529507571">

<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:okta:loa:2fa:any</saml2:AuthnContextClassRef>

<saml2:AuthnContextDecl>pwd</saml2:AuthnContextDecl>
<saml2:AuthnContextDecl>sms</saml2:AuthnContextDecl>
<saml2:AuthnContextDecl>mfa</saml2:AuthnContextDecl>
</saml2:AuthnContext>
</saml2:AuthnStatement>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[Create SAML app integrations](https://help.okta.com/okta_help.htm?id=ext_Apps_App_Integration_Wizard-saml) if you don’t have a SAML2 app configured.
Loading