Access policy for API grant types

Access policy can be applied to API-driven usage of OpenID Connect and OAuth 2.0. This API usage is most commonly known as the Resource Owner Password credentials grant type (ROPC), but also includes the JWT assertion-based grant type. These grant types unlike the authorization code and implicit grant types, have a fundamental difference in how they operate. No browser user-agent exists, and no requests are made to the /authorize endpoint. Because this browser endpoint is not used, the access policy for an application must be assessed differently.

When an access policy is applied, these fundamental business requirements are addressed:

  • Has the user authenticated sufficiently to access this application?
  • Is the authenticated user allowed to access this application?
  • Is the device or client context that is being used to access this application allowed?

In traditional browser flows these requirements are applied. If they are not met, the browser prompts for MFA, or it returns an error page to the user that halts the access. In an API grant type, these faculties are not all available. So the following issues must be addressed.

  • Receiving context from a client device.
  • Returning an MFA challenge, including,
    • The APIs that are needed to fulfill the MFA.
    • How to access the APIs.
API-driven grant types can still return an error, so a deny is largely unchanged.

The policyauth grant type

To effectively apply an access policy to an API only OAuth 2.0 flow, a new grant type is introduced. This grant type allows a client to present some context to the access policy before any authentication. This ability makes it possible to implement an enhanced user experience. For example, when a user presses a login button, before they're prompted to enter any credentials, they are evaluated according to the associated policy. If they do not satisfy the policy requirements, the user receives an error message that indicates that they're unable to authenticate or access the resource because of the policy requirements.

When the policyauth grant type is used, one of these responses is returned.
A deny
An error that indicates that access cannot be granted because of the policy.
A challenge
A token that can be used to access authentication APIs is returned, with a list of acceptable authentication factors.

MFA challenge responses from /token

When an access policy is applied to an API OAuth 2.0 flow, a challenge for MFA must become part of the API contract. The traditional methods of the OP performing the MFA steps as part of the request to /authorize are not possible.

When an MFA challenge is returned by /token,

  • The scope is mfa_challenge and no other scopes are returned.
  • An access token is issued.
    • The access token is entitled to access the necessary authentication APIs. It's important that this access token is used, and not a regular API client access token. This token is used to track already performed authentication factors and past actions across the grant.
    • The access token returns active: true from requests to /introspect. Any APIs that protect a resource server must, when MFA challenges are being used, implement a check that the scope returned from /introspect does not equal mfa_challenge.
  • Optionally, an array of factors that can be performed to satisfy this challenge allowedFactors is listed.

Presenting context to /token

The API client that performs a request to /token can present well-defined and arbitrary context information to /token to use in access policy evaluation.

Three mandatory pieces of context information must be included.

  • sessionId - An arbitrary session identifier that is issued and maintained by the OAuth client.
  • ipAddress - Because the OAuth client is responsible for the interactions with the user-agent, the user IP address must be explicitly provided.
  • userAgent - Similarly to IP address, the user-agent of the user must be explicitly provided.

More parameters can be included and context attribute conditions can be authored on these values.

Note: If the context parameter is not included in a request to /token, the access policy is not invoked.

Context is provided to /token in the form of base64 encoded JSON. An example JSON payload for context is:

{
    "sessionId":"MDNjZmQ3NDM2NjFmMDc5NzVmYTJmMT",
    "ipAddress":"129.42.38.10",
    "userAgent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}

Context information is considered trusted, as it is presented by an API client that was issued a secure set of client credentials. That API client must ensure it doesn't allow context to be arbitrarily presented by the consuming user-agent, which can then be used to circumvent business controls.

Context must be presented whenever an access policy is invoked across all the API grant types, policyAuth, JWT Bearer, ROPC and refresh token.

Satisfying mfa_challenge

To satisfy an MFA challenge that is returned by the /token endpoint, the authentication factors APIs can be used. These APIs are used to satisfy both first and second factor requirements. The access token that is returned in the mfa_challenge response is used to request the appropriate factor. After a successful factor completion, a JWT is returned. This JWT contains a few key pieces of information.

  • The grant_id that is derived from the access token that was used to request the factor API. This ID maintains correlation across the different requests to /token.
  • The factor that was performed and any factors that were performed previously.

This JWT is presented to /token as part of a jwtBearer grant type flow. The access policy is reassessed and a fully entitled token or another challenge is issued.

To receive a JWT from a factor verification, the query string parameter returnJwt=true must be included.
Note:
  • For transient factor APIs, the sub field of the JWT is populated with the transient information that is used in the request. For example, the email or the phone number rather than a userId.
  • When returnJwt=true is set, verification APIs that usually return a status code of 204 with no HTTP body, change their status code to a 200. They return the content-type of application/json and have a response like:
    {
        "assertion:"ey..."}
    For factor verifications that already return JSON, the assertion property is added to the response.

Applying access policy to different grant types

When you configure an application, an option exists of whether the access policy is applied to a specific grant type.

This configuration controls whether the access policy is evaluated on a request to /token that is based on the value of the grant_type parameter. This evaluation applies regardless of any prior invocations of /token for a specific grant.

This configuration can be applied to the following grant types:
policyauth
Access policy must always be enabled.
ROPC
Access policy can be disabled if the consumption of the ROPC grant type doesn't support the mfa_challenge response.
JWT Bearer
When access policy is disabled on the jwt-bearer grant type, an MFA cannot be done through the policyauth flow. An access policy won't run after the first factor is performed.
Refresh token
Can be applied to only a subset of refresh_token requests that use the context parameter original_grant_type as a context attribute condition.