Identity Cloud

OAuth 2.0

This guide covers concepts, configuration, and usage procedures for working with OAuth 2.0 and ForgeRock Access Management.

ForgeRock® Identity Platform serves as the basis for our simple and comprehensive Identity and Access Management solution. We help our customers deepen their relationships with their customers, and improve the productivity and connectivity of their employees and partners. For more information about ForgeRock and about the platform, see https://www.forgerock.com.

AM as the authorization server

In the role of the authorization server, AM authenticates resource owners and obtains their authorization in order to return access tokens to clients.

OAuth 2.0 concepts

RFC 6749, The OAuth 2.0 Authorization Framework lets a third-party application obtain limited access to a resource (usually user data), either on behalf of the resource owner, or in the application’s own behalf.

The main actors in the OAuth 2.0 authorization framework are the following:

Table 1. OAuth 2.0 Framework Actors
Actor Description

Resource owner (RO)

The owner of the resources. For example, a user that has several photos stored in a photo-sharing service.

The resource owner uses a user-agent, usually a web-browser, to communicate with the client.

Client

The third-party application that wants to obtain access to the resources. The client makes requests on behalf of the resource owner and with their authorization. For example, a printing service that needs to access the resource owner’s photos to print them.

AM can act as a client.

Authorization server (AS)

The authorization service that authenticates the resource owner and/or the client, issues access tokens to the client, and tracks their validity. Access tokens prove that the resource owner authorizes the client to act on their behalf over specific resources during a limited amount of time.

AM can act as the authorization server.

Resource server (RS)

The service hosting the protected resources. For example, a photo-sharing service. The resource server must be able to validate the tokens issued by the authorization server.

A website protected by a web or a Java agent can act as the resource server.

The following sequence diagram demonstrates the basic OAuth 2.0 flow:

OAuth 2.0 Protocol Flow
Figure 1. OAuth 2.0 Protocol Flow

Before configuring OAuth 2.0 in your environment, ensure you are familiar with the OAuth 2.0 authorization framework and the RFCs, Internet-Drafts, and standards that AM supports relating to OAuth 2.0.

When using AM as the authorization server, you can register confidential or public clients in the AM admin UI, or clients can register themselves with AM dynamically. For more information, see Client registration.

As the authorization server, AM supports the following:

Grant types
  • Authorization Code

  • Implicit

  • Resource Owner Password Credentials

  • Client Credentials

  • Device Flow

  • SAML v2.0 Profile for Authorization Grant

  • JWT Profile for OAuth 2.0 Authorization Grants

For more information, see OAuth 2.0 grant flows.

Client Authentication Standards
  • JWT profile for OAuth 2.0 client authentication

  • Mutual TLS

For more information, see OAuth 2.0 client authentication.

Other OAuth 2.0 standards
  • JWT proof-of-possession

For more information, see [oauth2-guide:oauth2-PoP-JWK].

Moreover, AM as an authorization server supports the following capabilities:

  • Remote consent services, which allows the consent-gathering part of an OAuth 2.0 flow to be handed off to a separate service.

    For more information, see Remote consent service.

  • Dynamic scopes, which allows customization of how scopes are granted to the client regardless of the grant flow used. You can configure AM to grant scopes statically or dynamically:

    • Statically (Default). You configure several OAuth 2.0 clients with different subsets of scopes and resource owners are redirected to a specific client depending on the scopes required. As long as the resource owner can authenticate and the client can deliver the same or a subset of the requested scopes, AM issues the token with the scopes requested. Therefore, two different users requesting scopes A and B to the same client will always receive scopes A and B.

    • Dynamically. You configure an OAuth 2.0 client with a comprehensive list of scopes and resource owners authenticate against it. When AM receives a request for scopes, AM’s authorization service grants or denies access scopes dynamically by evaluating authorization policies at runtime. Therefore, two different users requesting scopes A and B to the same client can receive different scopes based on policy conditions.

    For more information about granting scopes dynamically, see Authorization and policy decisions and Dynamic OAuth 2.0 authorization.

Security considerations

OAuth 2.0 messages involve credentials and access tokens that allow the bearer to retrieve protected resources. Therefore, do not let an attacker capture requests or responses. Protect the messages going across the network.

RFC 6749 includes a number of Security Considerations, and also requires Transport Layer Security (TLS) to protect sensitive messages. Make sure you read the section covering Security Considerations, and that you can implement them in your deployment.

Also, especially when deploying a mix of other clients and resource servers, take into account the points covered in RFC 6819, OAuth 2.0 Threat Model and Security Considerations, before putting your service into production.

Token storage location

AM OAuth 2.0-related services are stateless unless otherwise indicated; they do not hold any token information local to the AM instances. Instead, they either store the OAuth 2.0/OpenID Connect tokens in the core token service (CTS) token store, or present them to the client. This architecture lets you scale your AM infrastructure horizontally, because any server in the deployment can satisfy any token request.

The OAuth 2.0 token storage location is a property of the OAuth 2.0 service, configured by realm. You can configure each realm to store tokens in the CTS token store, or to hand the tokens to the clients as required.

Both CTS-based and client-based token configurations support all of AM’s OAuth 2.0 features. Before you decide to keep CTS-based tokens or to configure client-based tokens, consider the information in the following list:

CTS-based OAuth 2.0 tokens (previously referred to as stateful tokens)
  • The CTS token store is the authoritative source for the tokens. AM returns a reference to the token to the client. That reference does not contain any of the token information. In the following example, the reference is stored in the access_token property:

{
  "access_token": "sbQZuveFumUDV5R1vVBl6QAGNB8",
  "scope": "write",
  "token_type": "Bearer",
  "expires_in": 3599
}
  • CTS-based tokens are configured by default for all realms.

  • Clients cannot access the tokens other than to introspect them, making tokens less vulnerable to tampering attacks.

  • AM does not cache CTS-based tokens in memory. Therefore, every time a client presents a token ID in a request, AM checks if the token exists in the CTS token store (in case it has been revoked) and, if available, retrieves its information.

    Reading from and writing to the CTS token store incurs overhead for the CTS DS instances.

  • Tokens can only be introspected using a call to the authorization server.

Client-based OAuth 2.0 tokens (previously referred to as stateless tokens)
  • AM returns the token to the client after successfully completing one of the grant flows. In the following example, the token is stored in the access_token property:

{
   "access_token":"eyJ0eXAiOiJKV1QiLOT05FIiwiYWxnQY1lIjoxNTM5MDEzMzYyLsbSI6Ii8iLCj…​.",
   "scope":"write",
   "token_type":"Bearer",
   "expires_in":3599
}

A decoded access token produces JSON structures similar to the following:

{
     typ: "JWT",
     zip: "NONE",
     alg: "HS256"
}
{
     sub: "(usr!myClient)",
     subname" "myClient",
     cts: "OAUTH2_STATELESS_GRANT",
     auditTrackingId: "f20f4099-5248-4399-a7f0-2d54d4020099-108676",
     iss: "https://<tenant-name>.forgeblocks.com/am/oauth2",
     tokenName: "access_token",
     token_type: "Bearer",
     authGrantId: "1LUgI8zcDWqcfEnnLdZDnNqA2wc",
     aud: "myClient",
     nbf: 1539075967,
     grant_type: "client_credentials",
     scope: [
      "write"
     ],
     auth_time: 1539075967,
     realm: "/alpha",
     exp: 1539079567,
     iat: 1539075967,
     expires_in: 3600,
     jti: "FTQT6eZkDhm6PHEaSthORoTLB80"
}
[signature]
  • Token size may be a concern if tokens need to be sent in a header, since they are larger than the token reference returned for CTS-based tokens.

    The size of the client-based tokens also increases when you customize AM to store additional attributes in the tokens. You are responsible for ensuring that the size of the token does not exceed the maximum header size allowed by your end users' browsers.

  • Can be configured by realm.

  • Tokens are presented to the client after successfully completing an OAuth 2.0 grant flow. Therefore, tokens are vulnerable to tampering attacks and you should configure AM to sign and encrypt them.

  • AM does not store the decrypt sequence of the token in memory, so decrypting and verifying tokens incurs overhead for the AM instances.

  • Token denylisting is a feature that maintains a list of revoked tokens and authorization codes stored in the CTS token store. This feature protects against replay attacks, and it is always enabled for client-based tokens.

    Each time a client presents a client-based token in a request, AM checks the CTS token store to see whether the token has been revoked. If it has not been revoked, AM decrypts the token to retrieve its information.

    Client-based refresh tokens have corresponding entries in a CTS allowlist, rather than a blacklist. When presenting a client-based refresh token, AM checks that a matching entry is found in the CTS allowlist, and prevents reissue if the record does not exist.

    Adding a client-based OAuth 2.0 token to the blacklist removes the associated refresh token from the allowlist.

  • Clients can introspect the tokens without calling the authorization server. This can be advantageous in global deployments where keeping the CTS token store replication in sync fast enough to serve clients at any time by any server proves difficult. For more information about configuring client-based OAuth 2.0, see Configure AM for client-based OAuth 2.0 tokens.

AM as client and resource server

When AM functions as an OAuth 2.0 client, it provides a session after successfully authenticating the resource owner and obtaining authorization. The client can then access resources protected by agents.

To configure AM as an OAuth 2.0 client, use OAuth 2.0/OpenID Connect nodes as part of the authentication journey.

The following sequence diagram shows how the client gains access to protected resources in the scenario where AM functions as both authorization server and client:

OAuth 2.0 Client and Authorization Server
Figure 2. OAuth 2.0 Client and Authorization Server

As the OAuth 2.0 client functionality is implemented as an AM authentication nodes, you do not need to deploy your own resource server implementation when using AM as an OAuth 2.0 client. Use web or Java agents or IG to protect resources.

Use your own client and resource server

AM returns bearer tokens as described in RFC 6750, The OAuth 2.0 Authorization Framework: Bearer Token Usage. Notice in the following example JSON response to an access token request that AM returns a refresh token with the access token. The client can use the refresh token to get a new access token as described in RFC 6749:

{
  "expires_in": 599,
  "token_type": "Bearer",
  "refresh_token": "f6dcf133-f00b-4943-a8d4-ee939fc1bf29",
  "access_token": "f9063e26-3a29-41ec-86de-1d0d68aa85e9"
}

In addition to implementing your client, the resource server must also implement the logic for handling access tokens. The resource server can use the /oauth2/introspect endpoint to determine whether the access token is still valid, and to retrieve the scopes associated with the access token. For an example of the values returned by the endpoint, see /oauth2/introspect.

Related information:

Authorization server configuration

Configure the OAuth2 provider service to expose the OAuth 2.0 endpoints and OAuth 2.0 administration REST endpoints.

  1. In the AM admin UI, go to Realms > Realm Name > Services, and click Add a Service.

  2. From the drop-down list, select the OAuth2 Provider service, leave the remaining fields empty, and click Create.

  3. On the OAuth 2.0 provider page, select the Advanced tab.

  4. Configure the Grant Types that clients will be able to use to request access, refresh, and ID tokens.

    Grant types reference
    Implicit
    SAML2
    Refresh Token
    Resource Owner Password Credentials
    Client Credentials
    Device Code
    Authorization Code
    Back Channel Request
    UMA
    JWT Bearer
    Token Exchange

    Related information:

  5. Configure Persistent Claims

    Persistence lets you retain custom claims when you refresh an access token.

    In the Persistent Claims field, enter the claims that must be persisted between tokens. When an access token is refreshed, any claims that are listed here will be on the new token.

    • These claims are added before the access token modification script, allowing you to manipulate them in the modification script. For example, if a token has a claim called hostname that you want to be persisted when the token is refreshed, you could add that claim to the Persistent Claims list. You could then modify the script to persist that hostname in the new token, if it exists, or to add a hostname to the new token, if it does not exist.

    • Only custom, non-standard claims can be persisted. Standard claims such as scope (defined in the OAuth2 specification) and auditTrackingId (defined by default in AM) cannot be persisted.

  6. For other configuration options, see Additional configuration.

Additional configuration

The OAuth 2.0 provider is highly configurable:

  • To configure the OAuth 2.0 provider in the AM admin UI, go to Realms > Realm Name > Services, and select OAuth2 Provider.

  • To adjust global OAuth 2.0 provider defaults, go to Configure > Global Services, and click OAuth2 Provider.

See the OAuth2 Provider reference section for details on each of the fields in the provider.

Table 2. OAuth 2.0 provider configuration options
Task Resources

Configure the authorization server to issue refresh tokens

Learn why refresh tokens are useful in your environment, how to configure AM to issue them, and how to request them.

Adjust the lifetimes of tokens and codes

If necessary, adjust the lifetimes for authorization codes (a lifetime of 10 minutes or less is recommended in RFC 6749), access tokens, and refresh tokens.

Configure them on the Core tab of the provider.

N/A

Configure the OAuth 2.0 service to provide scopes dynamically

The OAuth 2.0 provider can leverage the AM Authorization service to grant or deny scopes dynamically.

Decide how scopes appear in the consent pages

To change how scopes appear, configure the Client Registration Scope Whitelist field on the Advanced tab of the OAuth 2.0 provider.

Scopes may be entered as simple strings or pipe-separated strings representing the internal scope name, locale, and localized description. For example: read|en|Permission to view email messages in your account.

Decide how to manage consent

You can:

  • Allow users to save consent so the OAuth 2.0 provider remembers their consented scopes.

  • Allow clients to skip consent so no consent page is displayed to the resource owners.

  • Allow clients to revoke consent.

Configure a remote consent server

This is useful, for example, when your environment must hand off the consent-gathering part of the OAuth 2.0 flows to a separate service.

Configure the attribute AM uses to retrieve the user profile

This is useful, for example, in cases where the resource owner should log in with their email address instead of with a username.

Configure client-based tokens

Configure client-based tokens so that resource servers can directly introspect the tokens without making a call to AM.

Configure OpenID-Connect specific options

UMA providers also use these options.

Change the attribute used to retrieve the user profile

If you use an external identity repository where resource owners log in not with their user ID, but instead with their mail address or some other profile attribute, you must configure AM authentication to allow it.

For example, to configure AM so OAuth 2.0 resource owners can log in using their email address, stored on the LDAP profile attribute, mail, perform the following steps:

  1. On the OAuth2 provider Advanced tab, add the LDAP profile attribute to the User Profile Attribute(s) the Resource Owner is Authenticated On list, and save your changes.

  2. Go to Realms > Realm Name > Identity Stores > Identity Store Name > Authentication Configuration.

  3. Set the value of the Authentication Naming Attribute field to the LDAP attribute required.

    For example, mail.

  4. Create an LDAP decision node to use with the identity repository.

    Configure the following fields:

    • In the Attribute Used to Retrieve User Profile field, set the attribute to mail.

    • In the Attributes Used to Search for a User to be Authenticated list, add the mail attribute.

    • Save your changes.

  5. Ensure the resource owners use the authentication mechanism you configured.

    Specify the tree by using one or more of the methods below. AM checks for the configured value in the following order, using the first value found:

    1. For a specific access token REST request.

      Set the auth_chain parameter.

    2. Individually for a realm, overriding the realm-level setting below.

      Navigate to Realms > Realm Name > Services > OAuth2 Provider > Advanced, and set the Password Grant Authentication Service property.

    3. Individually for a realm.

      Navigate to Realms > Realm Name > Authentication > Settings > Core, and set the Organization Authentication Configuration property.

    4. Globally, for all realms.

      Navigate to Configure > Authentication > Core Attributes > Core, and set the Organization Authentication Configuration property.

For more information, see Configure AM for authentication.

Configure AM for client-based OAuth 2.0 tokens

When configured for client-based tokens, AM returns a token (instead of the token reference it returns when configured for CTS-based tokens) to the client after successfully completing one of the grant flows. For more information about client-based and CTS-based tokens, see Token storage location.

Enable client-based OAuth 2.0 tokens

These steps configure AM to issue client-based access and refresh tokens:

  1. In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider.

  2. On the Core tab, enable Use Client-Based Access & Refresh Tokens.

  3. Enable Issue Refresh Tokens and/or Issue Refresh Tokens on Refreshing Access Tokens.

  4. Save your changes.

  5. Configure either client-based token signature or client-based token encryption.

    Token signature is enabled by default when client-based tokens are enabled. By default, token signature is configured using a demo key that you must change in production environments. If you enable token encryption, token signature is disabled, because encryption is performed using direct symmetric encryption.

Configure client-based OAuth 2.0 token encryption

To protect OAuth 2.0 client-based access and refresh tokens, AM supports encrypting their JWTs using AES authenticated encryption. Because this encryption also protects the integrity of the JWT, you only need to configure AM to sign OAuth 2.0 client-based tokens if token encryption is disabled.

  1. Go to Realms > Realm Name > Services > OAuth2 Provider.

  2. On the Core tab, enable Use Client-Based Access & Refresh Tokens.

  3. On the Advanced tab, enable Client-Based Token Encryption.

  4. Save your changes.

    Client-based OAuth 2.0 access and refresh tokens will now be encrypted.

Client-based OAuth 2.0 token digital signatures

AM supports digital signature algorithms that secure the integrity of client-based tokens.

Client-based tokens must be signed and/or encrypted for security reasons. If your environment does not support encrypting OAuth 2.0 tokens, you must configure signing to protect them against tampering.

AM exposes the public key to validate client-based token signatures in its JWK URI. See /oauth2/connect/jwk_uri.

These steps configure the OAuth 2.0 provider to sign client-based tokens:

  1. Go to Realms > Realm Name > Services, and click OAuth2 Provider.

  2. On the Advanced tab, in the OAuth2 Token Signing Algorithm list, select the signing algorithm to use for signing client-based tokens.

  3. Save your changes.

    Client-based OAuth 2.0 access and refresh tokens will now be signed.

OAuth 2.0 scopes

OAuth 2.0 flows require scopes to limit the client’s access to the resource owner’s resources.

What are scopes?

Scopes are a way to restrict client access to the resource owner’s resources, as defined in the OAuth 2.0 Authorization Framework.

Scopes are not associated with data and, in practice, they are just concepts specified as strings that the resource server must interpret in order to provide the required access or resources to the client. The OAuth 2.0 framework does not define any particular value for scopes since they are dependent on the architecture of your environment.

For example, a client may request the write scope, which the resource server may interpret as that the client wants to save some new information in the user’s account, such as images or documents.

A client can request one or more scopes, which AM may display in the consent screen. If the resource owner agrees to share access to their resources, scopes are included in the access token.

For security reasons, AM only accepts scopes preconfigured in the Scope(s) or in the Default Scope(s) fields in the client profile (Realms > Realm Name > Applications > OAuth 2.0 > Clients > Client Name > Core).

AM checks the requested scopes against the Scope(s) field of the client’s profile. If the client requests a scope that is not preconfigured, AM returns an error, such as Unknown/invalid scope(s).

If a client does not request any scopes, AM uses the scopes configured in the Default Scope(s) field of the client’s profile. If none are configured, AM uses those configured in the Default Scope(s) field of the OAuth 2.0 provider.

If no scopes are configured by default, AM returns the No scope requested error. AM does not use the default scopes in any other circumstance.

The Client Registration Scope Whitelist field of the OAuth 2.0 provider restricts the scopes a client can register with. In that sense, it is used for OpenID Connect discovery and dynamic client registration only.

You can use this field, however, to configure how AM presents the scopes in the AM consent screen. By default, scopes are not configured to display in the consent screen. You can either disable the consent pages, or configure the scopes for display as described below.

Since scope names are arbitrary, in some cases, they would not be descriptive enough for the resource owner to understand their purpose. In other cases, you may not want the resource owner to see a particular scope because it is for internal uses only.

Configure scopes in the consent screen

You can configure the AM consent screen to show, for each scope, one of the following options:

The scope itself A localized description Neither the scope nor a description
The OAuth 2.0 AM user interface consent screen requesting access to the write scope.
The OAuth 2.0 AM user interface consent screen showing the English description of a scope.
The OAuth 2.0 AM user interface consent screen not showing scopes or descriptions

Configure how scopes appear in the consent screen by client or by realm (in the OAuth 2.0 provider service).

For examples, see the Client Registration Scope Allowlist field in the provider’s reference section or the Scope(s) field in Core Properties.

Note that client-level configuration overrides the configuration that is set at the provider level.

Special scopes

AM reserves the following special scopes that cannot be added during dynamic client registration:

am-introspect-all-tokens

Add this scope to the Scopes(s) field in a client profile to let the client introspect tokens issued to other clients, as long as all clients are registered in the same realm.

For example:

  1. Client A is registered in the /customers/NA realm, and it is issued a token there.

  2. Client B is registered in the /customers realm. It cannot introspect Client A’s token because they are not in the same realm. Client B can only introspect tokens from other clients registered in the /customers realm.

am-introspect-all-tokens-any-realm

Add this scope to the Scopes(s) field in a client profile to let the client introspect tokens issued to other clients, as long as they are registered in the realm of the introspecting client, or in a subrealm of it.

For example:

  1. Client A is registered in the /customers/NA realm, and it is issued a token there.

  2. Client B is registered in the /customers realm. It can introspect Client A’s token because the /customers/NA realm is a subrealm of the /customers realm.

    Client B can introspect tokens for any client registered in the /customer realm, or any subrealm of it.

For security reasons, give these scopes only to the clients that need them.

Related information:

Many of the OAuth 2.0/OpenID Connect flows require the user to explicitly agree to provide the client with access to their resources. This act of trust is one of the pillars of OAuth 2.0 and OpenID Connect.

Users grant consent based on scopes. In OAuth 2.0, scopes are a concept that limits the information to share with the client or the actions the client can do with the user’s data. In OpenID Connect, scopes can be mapped to specific user data, too. For example, AM maps the profile scope to a number of user profile attributes.

AM has built-in consent pages in its UI, but you can hand off the consent-gathering part of the flow to a separate service by configuring the Remote consent service.

By default, scopes are not configured to display in the consent pages. You can either disable the consent pages, or manually add scopes for display in the OAuth 2.0 provider configuration.

For OpenID Connect, customize claims for display in the provider configuration or at the client level.

AM let clients store the scopes to which the user has given consent to improve user experience. This is useful, for example, to minimize customer interaction. In the same way, AM let users revoke consent at any point in time.

In some circumstances, however, clients may need a mechanism to skip consent altogether; for example, for trusted application-to-application or service-to-service interaction.

Companies that have internal applications that use OAuth 2.0 or OpenID Connect can allow clients to skip consent and make consent confirmation optional so as not to disrupt their online experience.

Perform the following steps to configure the OAuth 2.0 service and an OAuth 2.0 client to skip consent:

  • Go to Realms > Realm Name > Services > OAuth 2.0 Provider > Consent.

  • Enable Allow Clients to Skip Consent.

  • Click Save Changes.

    1. Configure the OAuth 2.0 client to skip consent:

  • Go to Realms > Realm Name > Applications > OAuth 2.0 > Client Name > Advanced.

  • Enable Implied consent.

  • Save your changes.

    AM will now treat the requests from this client as if the resource owner/end user has already consented, and will not display consent pages during the flow.

Requesting the consent of resource owners and end users to share their data is extremely important. However, this does not mean that your company needs to ask for consent every time a user wants to use your services.

To provide a better user experience, AM can store the scopes for which a user has given consent in their user profile.

When the client requests a scope combination, AM checks if the user has already consented each scope within the combination. If AM can find the scopes across multiple saved consent entries, AM will not require the user to consent. If part of the requested scope combination is not found in any entry, AM will require the user to consent.

Consider an example where the user grants consent to the read scope on a first request and to the email and profile scopes on a second request. AM will not require consent for a request for the read and profile scopes.

To request the user to provide consent even if it is already saved, add the prompt=consent parameter to the request.

Resource owners/end users can also revoke consent provided on requests for access tokens at any given time. For more information, see Let users revoke consent.

Perform the following steps to configure AM to save consent:

  1. Create a multi-valued string syntax attribute in your identity store to save consent entries.

    For example, oauth2Consent.

  2. In the AM admin UI, go to Realms > Realm Name > Services > OAuth 2.0 provider > Consent.

  3. In the Saved Consent Attribute field, add the name of the attribute you created in the identity store.

  4. Save your changes.

    AM will now save the consented scopes in the identity repository and will only request consent when it cannot find the requested scopes.

Users of OAuth 2.0 clients can manage their authorized applications on their user page in the AM admin UI. For example, the user logs in to the AM admin UI as demo, and click Dashboard. In the Authorized Apps section, the users can view the client application and the scopes they saved consent during requests for access tokens. Clicking the kbd:[x] button will remove consent for those scopes.

Managing OAuth 2.0 authorization in the AM admin UI.
Figure 3. OAuth 2.0 self-service

AM supports OAuth 2.0 remote consent services, which allow the consent-gathering part of an OAuth 2.0 flow to be handed off to a separate service.

A remote consent service renders a consent page, gathers the result, signs and encrypts the result, and returns it to the authorization server.

During an OAuth 2.0 flow that requires user consent, AM can create a consent request JWT that contains the necessary information to render a consent gathering page. It does not send the actual values of the requested scopes.

Consent request JWT example and properties
{
  "clientId": "myClient",
  "iss": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha",
  "csrf": "gjeH2C43nFJwW+Ir1zL3hl8kux9oatSZRso7aCzI0vk=",
  "client_description": "",
  "aud": "rcs",
  "save_consent_enabled": true,
  "claims": {},
  "scopes": {
      "write": null
  },
  "exp": 1536229486,
  "iat": 1536229306,
  "client_name": "My Client",
  "consentApprovalRedirectUri": "https://openam.example.com:8443/openam/oauth2/authorize?client_id=MyClient&response_type=code&redirect_uri=https://application.example.com:8443/callback&scope=write&state=1234zy",
  "username": "demo"
}
iat

Specifies the creation time of the JWT.

iss

Specifies the name of the issuer - configured in the OAuth 2.0 provider service in AM.

aud

Specifies the name of the expected recipient of the JWT, in this case, the remote consent service.

exp

Specifies the expiration time of the JWT.

Use short expiration times, for example, 180 seconds, as the JWT is intended for use in machine-to-machine interactions.

csrf

Specifies a unique string that must be returned in the response to help prevent cross-site request forgery (CSRF) attacks.

AM generates this string from a hash of the user’s session ID.

client_id

Specifies the ID of the OAuth 2.0 client making the request.

client_name

Specifies the display name of the OAuth 2.0 client making the request.

client_description

Specifies a description of the OAuth 2.0 client making the request.

username

Specifies the username of the logged-in user.

Ensure you encrypt the JWT if the username could be considered personally identifiable information.
scopes

Specifies the requested scopes.

claims

Specifies the claims the request is making.

Use the claims field for additional information to display on the remote consent page that helps the user to determine if consent should be granted. For example, Open Banking OAuth 2.0 flows may include identifiers for a money transaction.

save_consent_enabled

Specifies whether to provide the user the option to save their consent decision.

If set to false, the value of the save_consent property in the consent response from the RCS must also be false.

consentApprovalRedirectUri

Specifies the URI to return the resource owner to after they have provided consent.

Acting as the authorization server, AM signs and encrypts the JWT.

The remote consent service decrypts the JWT, verifies the signature and other details, such as the validity of the aud, iss and exp properties, and renders the consent page to the resource owner.

After the remote consent service gathers the user’s consent, it creates a consent response JWT, encrypts and signs the response, and returns it to AM for processing.

Consent response JWT example and properties
{
  "clientId": "myClient",
  "iss": "rcs",
  "csrf": "gjeH2C43nFJwW+Ir1zL3hl8kux9oatSZRso7aCzI0vk=",
  "client_description": "",
  "aud": "https://openam.example.com:8443/openam/oauth2",
  "save_consent": true,
  "claims": {},
  "scopes": "[write]",
  "exp": 1536229430,
  "iat": 1536229250,
  "client_name": "My Client",
  "consentApprovalRedirectUri": "https://openam.example.com:8443/openam/oauth2/authorize?client_id=MyClient&response_type=code&redirect_uri=https://application.example.com:8443/callback&scope=write&state=1234zy",
  "username": "demo",
  "decision": true
}
iat

Specifies the creation time of the JWT.

iss

Specifies the name of the remote consent service.

Should match the value of the aud property received from AM.

aud

Specifies the name of the expected recipient of the JWT, in this case, AM acting as the AS.

Should match the value of the iss property received from AM.

exp

Specifies the expiration time of the JWT.

Use short expiration times, for example, 180 seconds, as the JWT is intended for use in machine-to-machine interactions.

decision

Specifies true if consent was provided, or `false ` if consent was withheld.

client_id

Specifies the ID of the OAuth 2.0 client making the request, matching the value provided in the request.

client_name

Specifies the display name of the OAuth 2.0 client making the request.

client_description

Specifies a description of the OAuth 2.0 client making the request.

scopes

Specifies an array of allowed scopes.

Must be equal to, or a subset of the array of scopes in the request.

save_consent

Specifies true if the user chose to save their consent decision, or false if they did not.

If save_consent_enabled was set to false in the request, save_consent must also be false.

consentApprovalRedirectUri

Specifies the URI to return the resource owner to after they have provided consent.

AM decrypts and verifies the signature of the consent response and other details, such as the validity of the aud, iss and exp properties, and processes the response. For example, it may save the consent decision if configured to do so.

If the remote consent server compresses the consent response JWT, note that by default, AM rejects JWTs that expand to a size larger than 32 KiB (32768 bytes).

Both AM and the remote consent service make the required public keys available from a jwk_uri URI, enabling the signing and encryption between the two servers.

Configuring a remote consent service requires completion of these high-level tasks:

Task Resources

Add the details of the remote consent service as an agent profile in AM

You can configure a single remote consent service in a realm, by adding the details to a remote consent agent profile.

The profile defines properties for signing and encrypting the consent request and consent response, redirect URI, and the jwk_uri URI details of the remote consent service.

Enable remote consent and specify the agent profile in AM’s OAuth 2.0 provider service.

Configure the remote consent service with AM’s jwk_uri URI details.

The remote consent service must be able to obtain from AM the required signature and decryption keys.

N/A

Configure AM to use a remote consent service

To add the details of the remote consent service as an agent profile:

  1. In the AM admin UI, go to Realms > Realm Name > Applications > Remote Consent, and select Add Remote Consent Agent.

  2. Enter an agent ID, for example, myRCSAgent, and select Create.

  3. If you will be using an HMAC algorithm for signing the JWTs, enter the shared symmetric key in the Remote Consent Service secret field.

    This step is not required when using other algorithms.

  4. Select the remote consent agent, and configure the properties as required.

    Remote consent agent properties
    Group

    Configure several remote consent agent profiles by assigning them to a group.

    Default value: none

    amster attribute: agentgroup

    Remote Consent Service secret

    If the remote consent agent needs to authenticate to AM, enter the password it will use.

    amster attribute: userpassword

    Redirect URL

    Specify the URL to which the user should be redirected during the OAuth 2.0 flow to obtain their consent.

    The AM example remote consent service provides an /oauth2/consent path to obtain consent from the user.

    Example: https://rcs.example.com:8443/openam/oauth2/consent

    amster attribute: remoteConsentRedirectUrl

    Enable consent request Encryption

    Specify whether to encrypt the consent request JWT sent to the remote consent service.

    Default: true

    amster attribute: remoteConsentRequestEncryptionEnabled

    Consent request Encryption Algorithm

    Specify the encryption algorithm used to encrypt the consent request JWT sent to the remote consent service.

    AM supports the following encryption algorithms:

    • A128KW - AES Key Wrapping with 128-bit key derived from the client secret.

    • A192KW - AES Key Wrapping with 192-bit key derived from the client secret.

    • A256KW - AES Key Wrapping with 256-bit key derived from the client secret.

    • RSA-OAEP - RSA with Optimal Asymmetric Encryption Padding (OAEP) with SHA-1 and MGF-1.

    • RSA-OAEP-256 - RSA with OAEP with SHA-256 and MGF-1.

    • RSA1_5 - RSA with PKCS#1 v1.5 padding.

    • dir - Direct encryption with AES using the hashed client secret.

    Default value: RSA-OAEP-256

    amster attribute: remoteConsentRequestEncryptionAlgorithm

    Consent request Encryption Method

    Specify the encryption method used to encrypt the consent request JWT sent to the remote consent service.

    AM supports the following encryption methods:

    • A128GCM, A192GCM, and A256GCM - AES in Galois Counter Mode (GCM) authenticated encryption mode.

    • A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 - AES encryption in CBC mode, with HMAC-SHA-2 for integrity.

    Default value: A128GCM

    amster attribute: remoteConsentRequestEncryptionMethod

    Consent response signing algorithm

    Specify the algorithm used to verify a signed consent response JWT received from the remote consent service.

    AM supports signing algorithms listed in JSON Web Algorithms (JWA): "alg" (Algorithm) Header Parameter Values for JWS:

    • ES256 - ECDSA with SHA-256 and NIST standard P-256 elliptic curve.

    • ES384 - ECDSA with SHA-384 and NIST standard P-384 elliptic curve.

    • ES512 - ECDSA with SHA-512 and NIST standard P-521 elliptic curve.

    • HS256 - HMAC with SHA-256.

    • HS384 - HMAC with SHA-384.

    • HS512 - HMAC with SHA-512.

    • RS256 - RSASSA-PKCS-v1_5 using SHA-256.

    Default value: RS256

    amster attribute: remoteConsentResponseSigningAlg

    Consent response encryption algorithm

    Specify the encryption algorithm used to decrypt the consent response JWT received from the remote consent service.

    AM supports the following encryption algorithms:

    • A128KW - AES Key Wrapping with 128-bit key derived from the client secret.

    • A192KW - AES Key Wrapping with 192-bit key derived from the client secret.

    • A256KW - AES Key Wrapping with 256-bit key derived from the client secret.

    • RSA-OAEP-256 - RSA with OAEP with SHA-256 and MGF-1.

    • dir - Direct encryption with AES using the hashed client secret.

    The decryption key used depends on the algorithm chosen. The relevant secret IDs and the default decryption key aliases are shown in the table below: The following table shows the secret ID mapping used to decrypt remote consent responses:

    Secret ID Default Alias Algorithms(1)

    am.services.oauth2.remote.consent.response.decryption

    test

    RSA-OAEP-256

    (1) If you select an algorithm other than RSA-OAEP-256 for decrypting consent responses, the value of the Remote Consent Service secret property is used, instead of an entry from the secret stores.

    Default value: RSA-OAEP-256

    amster attribute: remoteConsentResponseEncryptionAlgorithm

    Consent Request Signing Algorithm

    Specify the algorithm used to sign the consent request JWT sent to the remote consent service.

    The signing key used depends on the algorithm chosen. The relevant secret IDs and the default signing key aliases are shown in the table below:

    The following table shows the secret ID mappings used to sign remote consent requests:

    Secret ID Default Alias Algorithms(1)

    am.applications.agents.remote.consent.request.signing.ES256

    es256test

    ES256

    am.applications.agents.remote.consent.request.signing.ES384

    es384test

    ES384

    am.applications.agents.remote.consent.request.signing.ES512

    es512test

    ES512

    am.applications.agents.remote.consent.request.signing.RSA

    rsajwtsigningkey

    RS256
    RS384
    RS512
    PS256
    PS384
    PS512

    (1) If you select an HMAC algorithm for signing consent requests (HS256, HS384, or HS512), the value of the Remote Consent Service secret property is used, instead of an entry from the secret stores.

    Since the HMAC secret is shared between AM and the remote consent client, a malicious user compromising the client could potentially create tokens that AM would trust. Therefore, to protect against misuse, AM also signs the token using a non-shared signing key configured in the am.services.oauth2.jwt.authenticity.signing secret ID.

    Default value: RS256

    amster attribute: remoteConsentRequestSigningAlgorithm

    Consent response encryption method

    Specify the encryption method used to decrypt the consent response JWT received from the remote consent service.

    AM supports the following encryption methods:

    • A128GCM, A192GCM, and A256GCM - AES in Galois Counter Mode (GCM) authenticated encryption mode.

    • A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 - AES encryption in CBC mode, with HMAC-SHA-2 for integrity.

    Default value: A128GCM

    amster attribute: remoteConsentResponseEncryptionMethod

    Public key selector

    Specify whether the remote consent service provides its public keys using a JWKs_URI, or manually in JWKs format.

    If JWKs is selected, you must enter the keys in the Json Web Key property. Otherwise complete the JWKs URI-related properties.

    Default: JWKs_URI

    amster attribute: remoteConsentRedirectUrl

    Json Web Key URI

    Specify the URI from which AM can obtain the remote consent service’s public keys.

    The AM example remote consent service provides an /oauth2/consent/jwk_uri path to provide the public keys.

    Example: http://rcs.example.com:8080/openam/oauth2/consent/jwk_uri

    amster attribute: jwksUri

    JWKs URI content cache timeout in ms

    Specify the amount of time, in milliseconds, that the content of the JWKs' URI is cached for before being refreshed. Caching the content avoids fetching it for every token encryption or validation.

    Default: 3600000

    amster attribute: com.forgerock.openam.oauth2provider.jwksCacheTimeout

    JWKs URI content cache miss cache time

    Specify the amount of time, in milliseconds, that AM waits before fetching the URI’s content again when a key ID (kid) is not in the JWKs that are already cached.

    For example, if a request comes in with a kid that is not in the cached JWKs, AM checks the value of JWKs' URI content cache miss cache time. If the amount of time specified in this property has already passed since the last time AM fetched the JWKs, AM fetches them again. Otherwise, the request is rejected.

    Use this property as a rate limit to prevent denial-of-service attacks against the URI.

    Default: 60000

    amster attribute: com.forgerock.openam.oauth2provider.jwkStoreCacheMissCacheTime

    Json Web Key

    If the Public key selector: property is set to JWKs, specify the remote consent service’s public keys, in JSON Web Key format.

    Example:

    {
      "keys": [
        {
          "kty": "RSA",
          "kid": "RemA6Gw0...LzsJ5zG3E=",
          "use": "enc",
          "alg": "RSA-OAEP-256",
          "n": "AL4kjz74rDo3VQ3Wx...nhch4qJRGt2QnCF7M0",
          "e": "AQAB"
        },
        {
          "kty": "RSA",
          "kid": "wUy3ifIIaL...eM1rP1QM=",
          "use": "sig",
          "alg": "RS256",
          "n": "ANdIhkOZeSHagT9Ze...ciOACVuGUoNTzztlCUk",
          "e": "AQAB"
        }
      ]
    }

    amster attribute: jwkSet

    Consent Request Time Limit

    Specify the amount of time, in seconds, for which the consent request JWT sent to the remote consent service should be considered valid.

    Default: 180

    amster attribute: requestTimeLimit

  5. Save your changes.

    The Remote Consent Agent profile is now available for selection in the OAuth 2.0 provider. See Configure the OAuth 2.0 provider to use a remote consent agent profile.

Configure the OAuth 2.0 provider to use a remote consent agent profile

To add the details of the remote consent agent profile to an OAuth 2.0 provider service:

  1. In the AM admin UI, go to Realms > Realm Name > Services, and select OAuth2 Provider.

  2. On the []Consent tab:

    • Select Enable Remote Consent.

    • In the Remote Consent Service ID drop-down list, select the agent ID of the remote consent agent. For example, myRCSAgent.

  3. If required, modify the supported signing and encryption methods and algorithms used for the consent request and consent response JSON web tokens.

    Example
    Configure the service ID, and encryption and signing properties.
    Figure 4. Configuring RCS in an OAuth 2.0 Provider
  4. Save your changes.

    OAuth 2.0 flows by any client in the realm will now use the remote consent service. OAuth 2.0 clients in other realms are unaffected.

Client registration

You can register OAuth 2.0/OpenID Connect clients with the AM OAuth 2.0 authorization service by creating and configuring a client profile. When creating a client profile, you must provide at least the client identifier and client secret.

Alternatively, you can register a client dynamically. AM supports open registration, registration with an access token, and registration including a secure software statement issued by a software publisher.

You can also create an OAuth 2.0 client profile group. OAuth 2.0 clients within a group can specify one or more properties that inherit their values from the group, allowing configuration of multiple OAuth 2.0 clients simultaneously. For more information, see Configure a client profile group.

Create and configure a client profile

  1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients.

  2. Click Add Client, and then provide the Client ID, Client secret, Redirection URIs, Scope(s), and Default Scope(s).

    Finally, click Create to create the profile.

  3. Adjust the configuration as needed using the inline help for hints and the following documentation:

    Core
    Group

    Set this field if you have configured an OAuth 2.0 client group.

    Status

    Specify whether the client profile is active for use or inactive.

    Client secret

    Specify the client secret as described by RFC 6749 in the section, Client Password.

    For OAuth 2.0/OpenID Connect 1.0 clients, AM uses the client password as the client shared secret key when signing the contents of the request parameter with HMAC-based algorithms, such as HS256.

    Client type

    Specify the client type.

    Confidential clients can maintain the confidentiality of their credentials, such as a web application running on a server where its credentials are protected. Public clients run the risk of exposing their passwords to a host or user agent, such as a JavaScript client running in a browser.

    Allow wildcard ports in redirection URIs

    Specify whether AM allows the use of wildcards (kbd:[*] characters) in the redirection URI port to match one or more ports.

    The URL configured in the redirection URI must be either localhost, 127.0.01, or ::1. For example, http://localhost:*/, https://127.0.0.1:80*/, or https://[::1]:*443/.

    Enable this setting, for example, for desktop apps that start a web server on a random free port during the OAuth 2.0 flow.

    Redirection URIs

    Specify client redirection endpoint URIs as described by RFC 6749 in the section, Redirection Endpoint. AM’s OAuth 2.0 authorization service redirects the resource owner’s user-agent back to this endpoint during the authorization code grant process. If your client has more than one redirection URI, then it must specify the redirection URI to use in the authorization request.

    Redirection URI values must NOT contain a fragment (kbd:[#]) and must be an exact match. Wildcards are only considered special characters for ports when the Allow wildcard ports in redirection URIs option is enabled.

    OpenID Connect clients require redirection URIs.

    Scope(s)

    Specify scopes that are to be presented to the resource owner when the resource owner is asked to authorize client access to protected resources.

    The openid scope is required for OpenID Connect clients. It indicates that the client is making an OpenID Connect request to the authorization server.

    Scopes can be entered as simple strings, such as openid, read, email, profile, or as a pipe-separated string in the format: scope|locale|localized description. For example, read|en|Permission to view email messages.

    Locale strings have the format: language_country_variant. For example, en, en_GB, or en_US_WIN. If the locale and pipe is omitted, the localized description is displayed to all users having undefined locales. If the localized description is omitted, nothing is displayed to all users. For example, a scope of read| would allow the client to use the read scope but would not display it to the user when requested.

    AM reserves special scopes to let resource servers introspect tokens issued to other clients. For more information, see Special Scopes.

    For more information about scopes and default scopes, and how AM uses them, see OAuth 2.0 scopes.

    Default Scope(s)

    Scopes that AM uses when the client does not request any during a grant flow.

    Specify scopes in scope or scope|locale|localized description format.

    Scopes defined in this property take the same format as those defined in Scope(s).

    For more information about scopes and default scopes, and how AM uses them, see OAuth 2.0 scopes.

    Client Name

    Specify a human-readable name for the client.

    Authorization Code Lifetime (seconds)

    Specify the time in seconds for an authorization code to be valid. If this field is set to zero, the authorization code lifetime of the OAuth2 provider is used.

    Default: 0

    Refresh Token Lifetime (seconds)

    Specify the time in seconds for a refresh token to be valid. If this field is set to zero, the refresh token lifetime of the OAuth2 provider is used. If the field is set to -1, the token will never expire.

    Default: 0

    Access Token Lifetime (seconds)

    Specify the time in seconds for an access token to be valid. If this field is set to zero, the access token lifetime of the OAuth2 provider is used.

    Default: 0

    Advanced
    Token Exchange Auth Level

    Specify the authentication level that will be set for tokens created as a result of token exchange when the subject token does not have an authentication level to begin with. For example, when exchanging an ID token for an access token.

    Default: 0

    Display name

    Specify a client name to display to the resource owner when the resource owner is asked to authorize client access to protected resources. Valid formats include name or locale|localized name .

    The Display name can be entered as a single string or as a pipe-separated string for locale and localized name, for example, en|My Example Company.

    Locale strings have the format: language_country_variant. For example, en, en_GB, or en_US_WIN. If the locale is omitted, the name is displayed to all users having undefined locales.

    Display description

    Specify a client description to display to the resource owner when the resource owner is asked to authorize client access to protected resources. Valid formats include description or locale|localized description.

    The Display description can be entered as a single string or as a pipe-separated string for locale and localized name, for example, en|The company intranet is requesting the following access permission.

    Locale strings have the format: language_country_variant. For example, en, en_GB, or en_US_WIN. If the locale is omitted, the name is displayed to all users having undefined locales.

    JavaScript Origins

    Specify the origin URLs that the client allows to make cross-origin resource sharing (CORS) requests to AM.

    For example, you might add the URL of a resource server being protected by an app that uses the ForgeRock SDKs, so that it can access the OAuth 2.0 endpoints from a different domain than AM.

    Wildcards are not supported; each value should be an exact match for the origin of the CORS request.

    The global CORS service collects the value of this property from each OAuth 2.0 client, and combines it with its own configuration.

    Request uris

    Specify request_uri values that a dynamic client would pre-register.

    URIs must be pre-registered in this field before the client can request them in the request_uri parameter.

    Grant Types

    Specify the set of OAuth 2.0 grant flows allowed for this client. The following flows are available:

    • Authorization Code

    • Back Channel Request

    • Implicit

    • Resource Owner Password Credentials

    • Client Credentials

    • Refresh Token

    • UMA

    • Device Code

    • SAML2

    • Token Exchange

    Default: Authorization Code. When registering clients dynamically, if no grant types are specified in the registration request, then the default Authorization Code grant type is assumed, and configured in the client. Any grant types selected in a client must also be enabled in the OAuth 2.0 provider service.

    Response Types

    Specify the response types that the client uses. The response type value specifies the flow that determine how the ID token and access token are returned to the client. For more information, see OAuth 2.0 Multiple Response Type Encoding Practices.

    Configure this field only if the client uses OAuth 2.0 / OpenID Connect grant flows that interact with the /oauth2/authorize endpoint.

    The following response types are available:

    • code. Specifies that the client requests an authorization code during the OAuth 2.0 Authorization Code Grant or the OpenID Connect Authorization Code Grant flows.

      This response type also applies to the Authorization Code grant with PKCE flows.

    • token. Specifies that the client requests an access token during the Implicit Grant flow.

    • id_token. Specifies that the client requests an ID token during the OpenID Connect Implicit Grant flow.

    • code token. Specifies that the client requests an access token and an authorization code during the OpenID Connect Hybrid Grant flow.

    • code id_token. Specifies that the client requests an authorization code and an ID token during the OpenID Connect Hybrid Grant flow.

    • code token id_token. Specifies that the client application requests an authorization code, an access token, and an ID token, during the OpenID Connect Hybrid Grant flow.

    • token id_token. Specifies that the client requests an access token and an ID token during the OpenID Connect Implicit Grant flow.

    Contacts

    Specify the email addresses of users who administer the client.

    Token Endpoint Authentication Method

    Specify the authentication method with which a client authenticates to AM (as an authorization server) at the token endpoint. The authentication method applies to OIDC requests with scope openid.

    • client_secret_basic. Clients authenticate with AM (as an authorization server) using the HTTP Basic authentication scheme after receiving a client_secret value.

    • client_secret_post. Clients authenticate with AM (as an authorization server) by including the client credentials in the request body after receiving a client_secret value.

    • private_key_jwt. Clients sign a JSON web token (JWT) with a registered public key.

    • tls_client_auth. Clients use a CA-signed certificate for mutual TLS authentication.

    • self_signed_tls_client_auth. Clients use a self-signed certificate for mutual TLS authentication.

    For more information, see OAuth 2.0 client authentication, and Client Authentication in the OpenID Connect Core 1.0 incorporating errata set 1 specification.

    Sector Identifier URI

    Specify the host component of this URI, which is used in the computation of pairwise subject identifiers.

    Subject Type

    Specify the subject identifier type, which is a locally unique identifier that will be consumed by the client. Select one of two options:

    • public. Provides the same sub (subject) value to all clients.

    • pairwise. Provides a different sub (subject) value to each client.

    Access Token

    Specify the registration_access_token value that you provide when registering the client, and then subsequently when reading or updating the client profile.

    Client URI

    Specify the URI containing further information about this client. The URI is displayed as a link in user-facing pages, such as consent pages.

    The URI can be made locale-specific by specifying a pipe-separated string in the format: URI|locale. For example, https://www.example.es:8443/aplicacion/informacion.html|es.

    Logo URI

    Specify the URI of a logo for the client. The logo is displayed in user-facing pages, such as consent pages.

    The logo can be made locale-specific by specifying a pipe-separated string in the format: URI|locale. For example, https://www.example.es:8443/aplicacion/imagen.png|es.

    Privacy Policy URI

    Specify the URI containing the client’s privacy policy documentation. The URI is displayed as a link in user-facing pages, such as consent pages.

    The URI can be made locale-specific by specifying a pipe-separated string in the format: URI|locale. For example, https://www.example.es:8443/aplicacion/legal.html|es.

    Implied Consent

    Enable the implied consent feature. When enabled, the resource owner will not be asked for consent during authorization flows. The OAuth2 Provider must also be configured to allow clients to skip consent.

    OAuth 2.0 Mix-Up Mitigation enabled

    Enable OAuth 2.0 mix-up mitigation on the authorization server side.

    Enable this setting only if this OAuth 2.0 client supports the OAuth 2.0 Mix-Up Mitigation draft, otherwise AM will fail to validate access token requests received from this client.

    Require Pushed Authorization Requests

    If enabled, the client must use the PAR endpoint to initiate authorization requests.

    Note that, even if this value is set to false, the authorization server may be configured to enforce PAR for all clients.

    OpenID Connect
    Claim(s)

    Specify one or more claim name translations that will override those specified for the authentication session. Claims are values that are presented to the user to inform them what data is being made available to the client.

    Claims can be in entered as simple strings, such as name, email, profile, or sub, or as a pipe-separated string in the format: scope|locale|localized description. For example, name|en|Full name of user.

    Locale strings have the format: language_country_variant. For example, en, en_GB, or en_US_WIN. If the locale and pipe is omitted, the localized description is displayed to all users having undefined locales. If the localized description is omitted, nothing is displayed to all users. For example, a claim of name| would allow the client to use the name claim but would not display it to the user when requested.

    If a value is not given, the value is computed from the OAuth2 provider.

    Post Logout Redirect URIs

    Specify one or more allowable URIs to which the user-agent can be redirected to after the client logout process.

    Client Session URI

    Specify the relying party (client) URI to which the OpenID Connect Provider sends session changed notification messages using the HTML 5 postMessage API.

    Default Max Age

    Specify the maximum time in seconds that a user can be authenticated. If the user last authenticated earlier than this value, then the user must be authenticated again. If specified, the request parameter max_age overrides this setting.

    Minimum value: 1.

    Default: 600

    Default Max Age Enabled

    Enable the default max age feature.

    Default ACR values

    Default Authentication Context Class Reference values.

    Specify strings that will be requested as Voluntary Claims by default in all incoming requests.

    Values specified in the acr_values request parameter or an individual acr claim request override these default values.

    OpenID Connect JWT Token Lifetime (seconds)

    Specify the time in seconds for a JWT to be valid. If this field is set to zero, the JWT token lifetime of the OAuth2 provider is used.

    Default: 0

    Backchannel Logout URL

    Specify the URL to where AM will send the logout token during backchannel logout.

    This URL can use the http or the https scheme, and may contain a port, a path, or query parameters, depending on the implementation of the relying party. For example, https://my-rp.example.com:443/logout.

    Backchannel Logout Session Required

    Specify whether to add the session ID (sid) to the logout token. The session ID identifies the relying party’s session with the provider.

    Signing and Encryption

    AM returns an error if the administrator tries to save a client profile configuration containing an unsupported signing or encryption algorithm on a client.

    For example, upon saving the configuration, AM will return an error if there is a typo on an algorithm, or a symmetric signing or encryption algorithm is configured on a public client: these algorithms are derived from the client’s secret, which public clients do not have.

    Clients registering dynamically must also send supported algorithms as part of their configuration, or AM will reject the registration request.

    Different features support different algorithms. Refer to the documentation or the UI for more information.

    Json Web Key URI

    Specify the URI that contains the client’s public keys in JSON web key format.

    When the client authenticates to AM using the private_key_jwt method, AM checks this field to find the public key to validate the JWT.

    JWKs URI content cache timeout in ms

    Specify the amount of time, in milliseconds, that the content of the JWKs' URI is cached for before being refreshed. Caching the content avoids fetching it for every token encryption or validation.

    Default: 3600000

    JWKs URI content cache miss cache time

    Specify the amount of time, in milliseconds, that AM waits before fetching the URI’s content again when a key ID (kid) is not in the JWK set already cached.

    For example, if a request comes in with a kid that is not in the cached JWKs, AM checks the value of JWKs' URI content cache miss cache time. If the amount of time specified in this property has already passed since the last time AM fetched the JWKs, AM fetches them again. Otherwise, the request is rejected.

    Use this property as a rate limit to prevent denial-of-service attacks against the URI.

    Default: 60000

    Token Endpoint Authentication Signing Algorithm

    Specify the JWS algorithm that must be used for signing JWTs used to authenticate the client at the Token Endpoint.

    JWTs that are not signed with the selected algorithm in token requests from the client using the private_key_jwt or client_secret_jwt authentication methods will be rejected.

    Default: RS256

    Json Web Key

    Raw JSON web key value containing the client’s public keys.

    ID Token Signing Algorithm

    Specify the signing algorithm that the ID token must be signed with.

    Enable ID Token Encryption

    Enable ID token encryption using the specified ID token encryption algorithm.

    ID Token Encryption Algorithm

    Specify the algorithm that the ID token must be encrypted with.

    Default value: RSA1_5 (RSAES-PKCS1-V1_5).

    ID Token Encryption Method

    Specify the method that the ID token must be encrypted with.

    Default value: A128CBC-HS256.

    Client ID Token Public Encryption Key

    Specify the Base64-encoded public key for encrypting ID tokens.

    Client JWT Bearer Public Key Certificate

    Specify the base64-encoded X509 certificate in PEM format. The certificate is never used during the signing process, but is used to obtain the client’s JWT bearer public key. The client uses the private key to sign client authentication and access token request JWTs, while AM uses the public key for verification.

    The following is an example of the certificate:

    -----BEGIN CERTIFICATE-----
    MIIDETCCAfmgAwIBAgIEU8SXLj.....
    -----END CERTIFICATE-----

    You can generate a new key pair alias by using the Java keytool command.

    For example:

    $ keytool \
    -list \
    -alias myAlias \
    -rfc \
    -storetype JCEKS \
    -keystore myKeystore.jceks \
    -keypass myKeypass \
    -storepass myStorepass
    Alias name: myAlias
    Creation date: Oct 27, 2020
    Entry type: PrivateKeyEntry
    Certificate chain length: 1
    Certificate[1]:
    -----BEGIN CERTIFICATE-----
    MIIDETCCAfmgAwIBAgIEU8SXLj…​
    -----END CERTIFICATE-----

    For more information, see Authenticating Clients Using JWT Profiles.

    Public key selector

    Select the format of the public keys for JWT profile client authentication and ID token encryption. Valid formats are:

    • JWKs_URI

      Configure a URI that exposes the client public keys in the Json Web Key URI field, and ensure the following related properties have sensible values for your environment:

      • JWKs URI content cache timeout in ms

      • JWKs URI content cache miss cache time

    • JWKs

      Enter a JWK Set containing one or more keys in the Json Web Key field. For example:

      {
          "keys": [
              {
                  "kty": "RSA",
                  "n": ...
              },
              ...
          ]
      }
    • X509

      Enter a key object or a single certificate in one of the following fields, depending on the feature you are configuring:

      • (ID token encryption) Client ID Token Public Encryption Key. Requires an RSA public key object in X.509 PEM format. For example:

        -----BEGIN PUBLIC KEY-----
        ......
        -----END PUBLIC KEY-----
      • (JWT client authentication) Client JWT Bearer Public Key. Requires a X.509 certificate in PEM format. For example:

        -----BEGIN CERTIFICATE-----
        .....
        -----END CERTIFICATE-----

    Default: JWKs_URI

    User info response format.

    Specify the output format from the UserInfo endpoint.

    Default: User info JSON response format.

    The supported output formats are as follows:

    • User info JSON response format.

    • User info encrypted JWT response format.

    • User info signed JWT response format.

    • User info signed then encrypted response format.

    For more information on the output format of the UserInfo Response, see Successful UserInfo Response in the [ref]_OpenID Connect Core 1.0 incorporating errata set 1 _ specification.

    User info signed response algorithm

    Specify the JSON Web Signature (JWS) algorithm for signing UserInfo Responses. If specified, the response will be JSON Web Token (JWT) serialized, and signed using JWS.

    The default, if omitted, is for the UserInfo Response to return the claims as a UTF-8-encoded JSON object using the application/json content type.

    User info encrypted response algorithm

    Specify the JSON Web Encryption (JWE) algorithm for encrypting UserInfo Responses.

    If both signing and encryption are requested, the response will be signed then encrypted, with the result being a nested JWT.

    The default, if omitted, is that no encryption is performed.

    User info encrypted response encryption algorithm

    Specify the JWE encryption method for encrypting UserInfo Responses. If specified, you must also specify an encryption algorithm in the User info encrypted response algorithm property.

    AM supports the following encryption methods:

    • A128GCM, A192GCM, and A256GCM - AES in Galois Counter Mode (GCM) authenticated encryption mode.

    • A128CBC-HS256, A192CBC-HS384, and A256CBC-HS512 - AES encryption in CBC mode, with HMAC-SHA-2 for integrity.

    Default: A128CBC-HS256

    Request parameter signing algorithm

    Specify the JWS algorithm for signing the request parameter.

    Must match one of the values configured in the Request parameter Signing Algorithms supported property of the OAuth2 Provider service.

    Request parameter encryption algorithm

    Specify the algorithm for encrypting the request parameter.

    Must match one of the values configured in the Request parameter Encryption Algorithms supported property of the OAuth2 Provider service.

    Request parameter encryption method

    Specify the method for encrypting the request parameter.

    Must match one of the values configured in the Request parameter Encryption Methods supported property of the OAuth2 Provider service.

    Default: A128CBC-HS256

    Token introspection response format

    Specifies the format of the token introspection response. The possible values for this property are:

    • JSON response format

    • Signed JWT response format

    • Signed then encrypted JWT response format

      Even if the client has configured the response to be JSON-formatted, it can request a signed JWT by adding the "Accept: application/jwt" header to the request. However, when a client that is configured to use either of the JWT-formatted responses requests a JSON response, AM returns an error. For an example, see /oauth2/introspect.

      For related signing and encryption algorithms, see the following properties:

    • Token introspection response signing algorithm

    • Token introspection response encryption algorithm

    • Token introspection response encryption method

    Default: JSON response format

    Token introspection response signing algorithm

    Specifies the algorithm used to sign the token introspection response when it is formatted as a signed JWT.

    Must match a value configured in the Token Introspection Response Signing Algorithms Supported property of the OAuth2 Provider service.

    The signing key used depends on the algorithm chosen.

    Default: RS256

    Token introspection response encryption algorithm

    Specifies the algorithm used to encrypt the token introspection response when it is formatted as a signed then encrypted JWT.

    Must match a value configured in the Token Introspection Response Encryption Algorithms Supported property of the OAuth2 Provider service.

    The algorithms that are not specified as being derived from the client secret use the client’s public keys. For more information, see the Public key selector property.

    Default: RSA-OAEP-256

    Token introspection response encryption method

    Specifies the encryption method used to encrypt the token introspection response when it is formatted as a signed then encrypted JWT.

    Must match a value configured in the Token Introspection Response Encryption Methods Supported property of the OAuth2 Provider service.

    Default: A128CBC-HS256

    UMA
    Client Redirection URIs
    This property is for future use, and not currently active.

    Specify one or more allowable URIs to which the client can be redirected after the UMA claims collection process. The URIs must not contain a fragment (#).

    If multiple URIs are registered, the client MUST specify the redirection URI to be redirected to following approval.

    OAuth2 Provider Overrides
    Enable OAuth2 Provider Overrides

    Enables the OAuth 2.0 provider configuration to be overridden by the settings in this section.

    When enabled, these client-level attributes override the corresponding attributes set by the OAuth 2.0 provider service or group.

    The overriding attributes will only apply if this setting is enabled.

    Issue Refresh Tokens

    Whether to issue a refresh token when returning an access token.

    Issue Refresh Tokens on Refreshing Access Tokens

    Whether to issue a refresh token when refreshing an access token.

    Use Policy Engine for Scope decisions

    With this setting enabled, the policy engine is consulted for each scope value that is requested.

    Scope decisions based on the policy engine are determined in the following way:

    • If a policy returns an action of GRANT=true, the scope is consented automatically, and the user is not consulted in a user-interaction flow.

    • If a policy returns an action of GRANT=false, the scope is not added to any resulting token, and the user will not see it in a user-interaction flow.

    • If no policy returns a value for the GRANT action:

      • For user-facing grant types, such as the authorization or device code flows, the user is asked for consent or saved consent is used.

      • For grant types that are not user-facing, such as those using password or client credentials, the scope is not added to any resulting token.

    OAuth2 Access Token Modification Script

    The script that is executed when issuing an access token. The script can change the access token’s internal data structure to include or exclude particular fields.

    OAuth2 Access Token May Act Script

    The script that is executed when issuing an access token explicitly to modify the may_act claim placed on the token.

    OIDC ID Token May Act Script

    The script that is executed when issuing an OpenID Connect ID token explicitly to modify the may_act claim placed on the token.

    OIDC Claims Script

    The script that is run when issuing an ID token or making a request to the userinfo OpenID Connect endpoint. Use this script to retrieve claim values based on an issued access token.

    Overrideable Id_Token Claims

    List of claims in the ID token that can be overridden in the OIDC claims script. These should be the subset of the core OpenID Connect claims; for example aud or azp.

    Custom Login URL Template

    Supports Freemarker syntax, with the following variables:

    Variable

    Description

    gotoUrl

    The URL to redirect to after login.

    acrValues

    The Authentication Context Class Reference (acr) values for the authorization request.

    realm

    The AM realm the authorization request was made on.

    service

    The name of the AM authentication tree requested to perform resource owner authentication.

    locale

    A space-separated list of locales, ordered by preference.

    The following example template redirects users to a non-AM front end to handle login, which will then redirect back to the /oauth2/authorize endpoint with any required parameters:

    http://mylogin.com/login?goto=${goto}<#if acrValues??>&acr_values=${acrValues}</#if><#if realm??>&realm=${realm}</#if><#if module??>&module=${module}</#if><#if service??>&service=${service}</#if><#if locale??>&locale=${locale}</#if>

    The default AM login page is constructed using the base URL source service.
    Use Client-Based Access & Refresh Tokens

    When enabled, AM issues access and refresh tokens that can be inspected by resource servers.

    Encrypt Client-Based Tokens

    Whether client-based access and refresh tokens should be encrypted.

    Enabling token encryption will disable token signing as encryption is performed using direct symmetric encryption.

    Allow Clients to Skip Consent

    If enabled, clients can be configured so that the resource owner will not be asked for consent during authorization flows.

    Enable Remote Consent

    Enables consent to be gathered by a separate service.

    Remote Consent Service ID

    The ID of an existing remote consent service agent.

    Some client configuration will depend on the configuration of the authorization server, and the type of client you are registering.

    Configuration tips

    Some basic points you must decide on are:

    • Is the client public or confidential?

    • What is its redirection URI?

    • Which scopes does it need?

    • What’s the name this client will show as in the UI pages?

    • Which grant types the client can use to request tokens?

    • Which tokens can this client request?

    • In the case of an OpenID Connect client:

      • If the client is confidential, which authentication method will it use?

      • Which claims does the client need?

  4. When finished, save your work.

Configure a client profile group

  1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0.

    1. To create a new OAuth 2.0 client profile group:

      On the Groups tab, select [label#]Add Group#, and specify a Group ID. Finally, select Create.

    2. To configure an OAuth 2.0 client profile group:

      On the Groups tab, select the group to configure.

  2. Adjust the configuration as needed.

  3. When finished, save your work.

    If the group is assigned to one or more OAuth 2.0 client profiles, changes to inherited properties in the group are also applied to the client profile.

    To assign a group to an OAuth 2.0 client profile, see Assign a group to a client profile and inherit properties.

Assign a group to a client profile and inherit properties

  1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0. On the Clients tab, select the client ID to which a group is to be assigned.

  2. On the Core tab, select the group to assign to the client from the Group drop-down.

    Adding or changing an assigned group will refresh the settings page. Unsaved property values will be lost.

    The inheritance (padlock) icons appear next to properties that support inheriting their value from the assigned group. Not all properties can inherit their value, such as, the Client secret property.

    Add OAuth 2.0 Clients to a group to inherit settings.
    Figure 5. OAuth 2.0 Client Profile Group Inheritance
  3. Inherit a property value from the group by selecting the inheritance button (the open padlock icon) next to the property.

    The value will be inherited from the group and the field will be locked.

    If you change the group, properties with inheritance enabled will inherit the value from the new group.

    If you remove the group, inherited property values are written to the OAuth 2.0 client profile, and become editable.

  4. When finished, save your work.

OAuth 2.0 client authentication

AM can authenticate OAuth 2.0/OpenID Connect clients by using the following methods:

Confidential clients holding a secret or a JWT bearer token assertion can authenticate with the authorization server using any of the above methods.

While confidential clients must always authenticate in one of the ways described in this section, public clients are not required to authenticate, because their information is intended to be public or they are used over insecure channels, so their secret could be easily snooped.

During authentication by HTTP POST without a client_id parameter, AM stores the POST data on the user-agent in an AUTH_REQUEST_ATTRIBUTES cookie. This cookie lets AM continue the authentication process across redirects. AM marks the cookie for deletion on the next successful OAuth 2.0 authorization.

OAuth 2.0 and OpenID Connect clients can use the same authentication methods. However, OpenID Connect clients must specify the method they are using in their client profiles.

Authenticate clients with form parameters

Clients that have a client secret can send the client ID in the client_id form parameter and the secret in the client_secret form parameter in the body of the request. For example:

$ curl \
--request POST \
--data "client_id=myClient" \
--data "client_secret=forgerock" \
…​

This is the simplest way to authenticate to any of the OAuth 2.0 endpoints, and the most insecure, since the client credentials are exposed. Ensure that communication with the authorization server happens over a secure protocol to protect the secret, and use this method in production only if the other methods are not available for your client.

OpenID Connect clients must also specify the authentication method they are using in their client profiles. See OpenID Connect client authentication.

Authenticate clients with authorization headers

Clients that have a client secret can send the client ID and the secret in a basic authorization header with the base64-encoded value of client_id:client_secret. For example:

$ curl \
--header "Authorization: Basic bXlDbGllbnQ6Zm9yZ2Vyb2Nr" \
--request POST \
…​

If the client ID or client secret contains characters that have special meaning in URL-encoded strings, such as percent (kbd:[%]) or plus (kbd:[+]) characters, you must first URL-encode the string before combining them with the colon character and base64-encoding the result. URL-encoding characters that do not have special meaning in URL-encoded strings will still work, but is unnecessary.

For example, for a client named example.com with a client secret of s=cr%t:

  1. URL-encode the client secret value and combine with the colon character.

    For example: example.com:s%3Dcr%25t.

    Note that you should not URL-encode the separating colon character.

  2. Base64-encode the entire string to obtain the basic authorization header.

    For example, ZXhhbXBsZS5jb206cyUzRGNyJTI1dA==.

Ensure that communication with the authorization server happens over a secure protocol to help protect the credentials.

OpenID Connect clients must also specify the authentication method they are using in their client profiles. See OpenID Connect client authentication.

Authenticate clients with JWT profiles

Clients can send a signed JWT to the authorization server as credentials instead of the client ID and/or secret, as per (RFC 7523) JWT Profile for OAuth 2.0 Client Authentication and Authorization Grants. The authorization server must be able to validate the JWT to authenticate the client.

The following diagram demonstrates the JWT Bearer client authentication flow:

JWT Bearer Client Authentication
Figure 6. JWT Bearer Client Authentication
  1. The client requests a JWT from the issuer.

    Clients usually generate their own JWTs before starting the OAuth 2.0/OpenID Connect flow, but they can delegate the task to a specific service in your environment if required. AM cannot generate JWTs for this purpose.

  2. The issuer returns a signed JWT to the client.

    The JWT must contain, at least, the following claims in the payload:

    • iss. Specifies the unique identifier of the JWT issuer. This could also be the client, or a third party.

    • sub. Specifies the principal who is the subject of the JWT. Must be set to the client ID.

    • aud. Specifies the authorization server that is the intended audience of the JWT. Must be set to the authorization server’s token endpoint. For example, https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token.

    • exp. Specifies the expiration time.

      Providing a JWT with an expiry time greater than 30 minutes causes AM to return a JWT expiration time is unreasonable error message.

    • jti. Specifies a random, unique identifier for the JWT.

      This claim is required if the client requests the openid scope, and optional otherwise.

    For more information about the JWT, read the RFC 7523 standard.

    The JWT issuer must digitally sign the JWT or have a Message Authentication Code (MAC) applied by the issuer. When the issuer is also the client, the client can sign the JWT by using a private key.

    AM ignores keys specified in JWT headers, such as `jku` and `jwe`. Regardless of who issues the JWT, you must configure the public key or HMAC secret in the client profile so AM can validate it:

    Configure certificates represented as PEM files
    1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Client Name > Signing and Encryption.

    2. In the Client JWT Bearer Public Key field, enter the public certificate. For example:

      -----BEGIN CERTIFICATE-----
      MIIDETCCAfmgAwIBAgIEU8SXLjAN...
      -----END CERTIFICATE-----

      You can only enter one certificate.

    3. In the Public key selector drop-down list, select X509.

    Configure Public Keys in JWK Format

    You can either enter the JWK Set in the client profile, or store the JWK Set in a URI that exposes it to AM:

    • To store the JWK Set in the client profile:

      1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Client Name > Signing and Encryption.

      2. In the Json Web Key field, enter the JWK Set. For example:

        {
          "keys": [
            {
              "alg": "RSA-OAEP-256",
              "kty": "RSA",
              "use": "sig",
              "kid": "RemA6Gw0...LzsJ5zG3E=",
              "n": "AL4kjz74rDo3VQ3Wx...nhch4qJRGt2QnCF7M0",
              "e": "AQAB"
            }
          ]
        }

        Enter a JWK Set with multiple JWKs if you plan to rotate certificates.

      3. In the Public key selector drop-down list, select JWKs.

    • To store the JWK Set in a URI:

      1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Client Name > Signing and Encryption.

      2. In the [.label]# Json Web Key URI# field, configure the URI that exposes the JWK Set.

        Ensure that the following related properties have sensible values for your environment:

        • JWKs URI content cache timeout in ms

        • JWKs URI content cache miss cache time

      Store a JWK Set with multiple JWKs if you plan to rotate certificates.

      1. In the Public key selector drop-down list, select JWKs_URI.

    Configure HMAC secrets
    1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Client Name > Core.

    2. In the Client secret field, enter the HMAC secret. For more information about the length of the secret, see the Symmetric Key Entropy section of the OpenID Connect specification.

      You can only enter one HMAC secret.

    OpenID Connect clients must also specify the authentication method they are using in their client profiles. See OpenID Connect client authentication.

  3. The client includes the JWT and a client assertion type in the call to the OAuth 2.0 endpoint in the following parameters:

    • client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer

    • client_assertion=my_JWT

    For example:

    $ curl \
    --request POST \
    --data "client_id=myClient" \
    --data "client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer"
    --data "client_assertion=eyAiYWxnIjogIlJTMjU2IiB9.eyAic3ViIjogImp3…​"
    …​
  4. The authorization server validates the JWT with the public key stored in the client profile.

  5. The authorization server issues a response to the client. This response may include, for example, an access token.

AM provides scriptable extension points for you to customize authentication journeys and extend AM functionality.

To view the sample scripts available to you, see Sample Scripts.

Proof-of-possession

Proof-of-possession is a way to ensure that the client sending a request to the resource server possesses a particular cryptographic key. In other words, it is a way of proving the identity of the client.

Configure proof-of-possession to control which clients access your resources, or to mitigate against token theft; a malicious user with an access token must also present the cryptographic key to access the resources.

JWK-based proof-of-possession

To implement JWK-based proof-of-possession, the client includes a JWK when making a request to the authorization server for an access token as per Proof-of-Possession Key Semantics for JSON Web Tokens (JWTs) spec. The JWK consists of the public key of a key pair generated by the client.

When the client presents the access token to a resource server, the resource server can cryptographically confirm proof-of-possession of the token by using the associated JWK to form a challenge-response interaction with the client.

OAuth 2.0 JWK-Based Proof-of-Possession Flow
Figure 7. OAuth 2.0 JWK-Based Proof-of-Possession Flow
JWK-based proof-of-possession flow explained
  1. The client requests an access token using any of the OAuth 2.0 grant flows, and includes a JWK in the request.

    This JWK consists of the public key of a key pair generated by the client.

  2. The authorization server returns the access token to the client:

    • If the authorization server is configured for CTS-based OAuth 2.0, it stores the JWK with the access token in the CTS token store and provides the client with the access token ID.

    • If the authorization server is configured for client-based OAuth 2.0, the access token is a JWT that contains the JWK embedded in it.

  3. The client requests access to the protected resources from the resource server.

  4. The resource server recovers the JWK associated with the access token:

    • If the resource server receives an access token ID (CTS-based OAuth 2.0), it introspects the access token ID to recover the JWK from the authorization’s server CTS token store.

    • If the resource server receives an access token JWT (client-based OAuth 2.0), it already has access to the JWK, which is embedded.

  5. The resource server creates a challenge using the JWK. Usually, these challenges are messages or nonces that have been encrypted with the JWK.

  6. The resource server sends the challenge to the client.

  7. The client solves the challenge using the private key of its key pair.

  8. The client sends the response to the challenge to the resource server.

  9. The resource server validates the response and allows access to the resource.

Obtain an access token using JWK-based proof-of-possession

  1. Generate a JSON web key pair for the OAuth 2.0 client.

    AM supports both RSA and elliptic curve (EC) key types. For testing purposes, you can use an online JSON web key generator, such as https://mkjwk.org/, to generate a key pair in JWK format. Be sure to store the full key pair, including the private key, in a secure location that is accessible by your OAuth 2.0 client.

    Your OAuth 2.0 client should never reveal the private key.

  2. Represent the public key of the key pair in JWK format.

    For example:

    {
      "jwk":{
        "alg":"RS256",
        "e":"AQAB",
        "n":"xea7Tb7rbQ4ZrHNKrg...QFXtJ-didSTtXWCWU1Qrcj0hnDjvkuUFWoSQ_7Q",
        "kty":"RSA",
        "use":"enc",
        "kid":"myPublicJSONWebKey"
      }
    }
    The jwe and jku formats are not supported; the public key must be represented in jwk format.
  3. Base64-encode the JWK.

    For example:

    ew0KICAgICJKV0siOiB7DQogICAgICAgICJhbGciOiAiUlMyNTYiLA0KICAgICAgICAiZSI6IC
    JBUUFCIiwNDQogICAgICAgICJraWQiOiAibXlQdWJsaWNKU09OV2ViS2V5Ig0KICAgIH0NCn0=
  4. The client includes the base64-encoded JWK as the value of the cnf_key parameter in the request to the authorization server for an access token.

    For example, in the Client credentials grant, the client makes a POST call to the authorization server’s token endpoint specifying, at least, the following parameters:

    • grant_type=client_credentials

    • cnf_key=your-base64-encoded-JWK

      Confidential clients can authenticate to the OAuth 2.0 endpoints in several ways. This example uses the following form parameters:

    • client_id=your-client-id

    • client_secret=your-client-secret

    For more information, see OAuth 2.0 client authentication.

    For example:

    $ curl \
    --request POST \
    --data "grant_type=client_credentials"\
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data "cnf_key=ew0KICAgICJKV0siOiB7DQogICAgICAgICJhb
                 GciOiAiUlMyNTYiLA0KICAgICAgICAiZSI6IC
                 JBUUFCIiwNDQogICAgICAgICJraWQiOiAibXl
                 QdWJsaWNKU09OV2ViS2V5Ig0KICAgIH0NCn0=" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"

    For more information about how to use the different OAuth 2.0 grant flows, see OAuth 2.0 grant flows.

    The authorization server returns the access token:

    • If the authorization server is configured to use CTS-based OAuth 2.0 tokens, the response will include an access token ID in the access_token property, which identifies the access token data stored on the server. For example:

    {
        "access_token":"f08f1fcf-3ecb-4120-820d-fb71e3f51c04",
        "scope":"profile",
        "token_type":"Bearer",
        "expires_in":3599
    }
    • If the authorization server is configured to use client-based OAuth 2.0 tokens, the response will be a JSON web token in the access_token, which has the JWK embedded within. The following example has shortened the access token for display purposes:

    {
        "access_token": "eyJ0eXAiOiJKV1QiLCHi51zbE3t…​zc2NjI3NDgsInNjb3zUOCVKCX0Se0",
        "scope": "profile",
        "token_type": "Bearer",
        "expires_in": 3599
    }
  5. The client now requests access to the protected resources from the resource server.

    If CTS-based OAuth 2.0 tokens are enabled, the resource server can make a POST request to the /oauth2/introspect endpoint to acquire the public key. The public key from the original JWK is returned in the cnf element:

    $ curl \
    --request POST \
    --header "Authorization: Basic bXlDbGllbnQ6Zm9yZ2Vyb2Nr" \
    --data "token=f08f1fcf-3ecb-4120-820d-fb71e3f51c04" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/introspect"
    {
        "active": true,
        "scope": "profile",
        "client_id": "myClient",
        "user_id": "myClient",
        "username":"myClient",
        "token_type": "access_token",
        "exp": 1477666348,
        "sub": "(age!myClient)",
        "subname": "myClient",
        "iss": "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root",
        "cnf": {
            "jwk": {
                "alg": "RS256",
                "e": "AQAB",
                "n": "xea7Tb7rbQ4ZrHNKrg…​QFXtJ-didSTtXWCWU1Qrcj0hnDjvkuUFWoSQ_7Q",
                "kty": "RSA",
                "use": "enc",
                "kid": "myPublicJSONWebKey"
            },
        "auth_level": 0
        }
    }
  6. The resource server should now use the public key to cryptographically confirm proof-of-possession of the token by the presenter; for example, with a challenge-response interaction.

    Successful completion of the challenge-response means that the client must possess the private key that matches the public key presented in the original request, and access to resources can be granted.

Refresh tokens

Refresh tokens (RFC 6749) are a type of token that can be used to obtain a new access token that may have identical or narrower scopes than the original. AM can issue refresh tokens during every OAuth 2.0/OpenID Connect grant flow except for the Implicit and the client credentials grant flows.

Why are refresh tokens useful?

Access tokens are short-lived because, if leaked, they grant potentially malicious users access to the resource owner resources. However, clients may need to access the protected data for periods of time that exceed the access token lifetime or when the resource owner is not available. In some cases, it is unreasonable to ask for the resource owner’s consent several times during the same operation.

Refresh tokens solve this problem by letting clients ask for a new access token without further interaction from the resource owner. While a potentially malicious user compromising an access token has access to the resource owner resources, one that holds a refresh token also needs to compromise the client ID and the client secret to be able to get an access token, since the client needs to authenticate to the token endpoint to obtain an access token using the refresh token.

Refresh tokens are long-lived by default, and AM lets you configure the lifetime of the tokens in the OAuth 2.0 provider settings, or in each client. By default, the configuration of the OAuth 2.0 provider is used. For more information, see OAuth2 Provider.

Refresh tokens can also be revoked. For more information, see /oauth2/token/revoke.

Configure AM to issue refresh tokens

AM can issue refresh tokens during the following actions:

  • When issuing an access token to the client after a successful OAuth 2.0 grant flow.

  • When the client successfully uses a refresh token to obtain a new access token.

When a new refresh token is issued, the old refresh token is deactivated.
  1. To let AM issue refresh tokens at the same time the access token is issued, go to Realms > Realm Name > Services > OAuth2 Provider > Core, and enable Issue Refresh Tokens.

    Note that you configure refresh tokens at the realm level. Consider carefully the types of clients registered to the realm before configuring AM to issue refresh tokens.

  2. To let AM issue refresh tokens when refreshing access tokens, go to Realms > Realm Name > Services > OAuth2 Provider > Core, and enable Issue Refresh Tokens on Refreshing Access Tokens.

  3. Save your changes.

  4. To configure a client to use the Refresh Token grant flow perform the following steps:

    • Go to Realms > Realm Name > Applications > OAuth 2.0 > Client Name > Advanced.

    • In the Grant Types field, add the Refresh Token grant type.

    • Save your changes.

Refresh an access token

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server with the following configuration:

    • Issue Refresh Tokens is enabled.

    • Issue Refresh Tokens on Refreshing Access Tokens is enabled.

    • The Refresh Token grant type is configured in the Grant Types field.

    For more information, see Authorization server configuration.

  • A confidential client called myClient is registered in AM with the following configuration:

    • Client secret: forgerock

    • Scopes: write read

    • Grant Types: Authorization Code Refresh Token

Perform the steps in the procedure to refresh an access token:

  1. The client obtains an access token and a refresh token using the Authorization Code Grant flow.

    For more information, see Authorization code grant.

    The example assumes the refresh token is qz1qx-9AYOkRp3AWcCZULvPitpM.

  2. The client makes a POST call to the authorization’s server token endpoint, specifying, at least, the following parameters:

    • grant_type=refresh_token

    • refresh_token=your-refresh-token

    For more information about the parameters supported by the /oauth2/access_token endpoint, see /oauth2/access_token.

Confidential clients can authenticate to the OAuth 2.0 endpoints in several ways. This example uses the following form parameters:

  • client_id=your-client-id

  • client_secret=your-client-secret

For more information, see OAuth 2.0 client authentication.

You must specify the realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/authorize.

For example:

$ curl --request POST \
--data "grant_type=refresh_token" \
--data "refresh_token=qz1qx-9AYOkRp3AWcCZULvPitpM" \
--data "client_id=myClient" \
--data "client_secret=forgerock" \
--data "scope=read" \
"https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"
{
   "access_token":"y-C_A1RKJIg-BUlKhp—​kv5Iywk",
   "refresh_token":"qdqVnFJK8FjiQAjYMaBuUY6z_HU",
   "scope":"read",
   "token_type":"Bearer",
   "expires_in":3599
}
  • The scope parameter is not required. By default, AM will issue an access token with the same scopes as the original token. This example restricts the new access token to the read scope.

  • AM has issued a new refresh token; the original refresh token is now inactive.

Macaroons as access and refresh tokens

Macaroons are a type of bearer token that can be used when issuing OAuth 2.0 access and refresh tokens. They can be used in place of regular access or refresh tokens, as they allow the sharing of a single token with multiple clients and resource servers without compromising security.

The idea behind it is that, rather than issuing multiple access tokens with different scopes for a set of clients, AM issues a macaroon access token with a broad scope to a client. The client then creates as many macaroons as needed from the single macaroon access token, restricting their scopes as required by using caveats. This is very useful, for example, in a microservice architecture where a single client can delegate tasks to other services, with a limited set of capabilities or bound by certain restrictions.

Caveats are restrictions placed on a macaroon that must be satisfied before using the token. Meaning, for example, that if the expiry time is past, the token is invalid.

Caveats that can be satisfied locally are referred to as first-party caveats, and caveats satisfied by a service external from AM are referred to as third-party caveats.

Third-party caveats and discharge macaroons

Third-party caveats are those that require the client to use a service other than AM to get proof that the condition specified by the caveat is satisfied. They are useful in situations where you have services external to AM that can make additional authorization checks relevant to the access token.

For example, consider a case where you have a service external to AM, akin to an IDP in a SAML v2.0 architecture, that you can query to know if the user related to the access token belongs to a particular user group.

The proof that the condition is satisfied is returned by the third party in a discharge macaroon, and the client must present both the access token macaroon and the discharge macaroon to get access to the resource.

The discharge macaroon can also have first-party caveats attached to it, such as expiry time. This allows for flows where the access token macaroon is long-lived and the discharge macaroon is not, which forces the client to acquire a new discharge macaroon to access the resource.

Any first-party caveats attached to the discharge macaroons will be treated as if they were caveats on the access token itself. For example, if the discharge macaroon limits the expiry time to five minutes, the introspection response will list the expiry time of the access token as five minutes even if the access token was valid for longer.

Another possible use case is related to transactional authorization. Consider a case where a payment is tied to a unique transaction; you could create a macaroon access token containing a third-party caveat that requires the client to obtain a one-time discharge macaroon from an external transactional service.

A third-party caveat has the following parts:

  • A hint describing where the client can find the third-party service, which is usually a URL.

  • A unique secret key to sign discharge macaroons, known as the discharge key.

  • An identifier for the third-party service to know which condition needs to be checked, and how to recover the discharge key.

    There is no standard format for the identifier part.

Which first-party caveats does AM support?

There is no standard format for caveats in macaroons, so AM has adopted a JSON-based syntax that mirrors the existing JWT-based token restrictions:

scope

Restricts the scope of the token. The returned scope will be the intersection of the original token scope and any scope caveats.

exp

Restricts the expiry time of the token. The effective expiry time is the minimum of the original expiry time and any expiry caveats added to the token. If you have appended more than one exp caveat, the most restrictive one applies.

cnf

Binds the access token to a client certificate. This means that a client can be issued with a regular access token and then can later bind it to their client certificate. You can only bind one client certificate to the macaroon. Any attempt to bind a new certificate with subsequent caveats is ignored.

aud

Restricts the audience of the token. The effective audience is the intersection of any audience restriction and any aud caveats.

AM returns any other caveats in a caveats object on the JSON introspection response.

OpenID Connect clients must ensure that the following information is present in the JSON:

  • The openid scope. For example, "scopes": ["profile", "openid"].

  • The id_token response type. For example, "response_types": ["code", "id_token code"].

Append caveats to macaroons

You append caveats to a macaroon through a macaroon library of your choosing. AM provides the /json/token/macaroon endpoint to add first-party caveats to a macaroon. You can also use this endpoint to inspect the caveats already appended.

Using OAuth 2.0 Endpoints with Macaroons

AM endpoints that support access tokens also support macaroons without further configuration. Endpoints will reject macaroons whose caveats are not satisfied.

When dealing with macaroons containing third-party caveats, use the X-Discharge-Macaroon header to pass a discharge macaroon.

Macaroons and CTS-based and client-based tokens

Macaroons are layered on top of the existing CTS-based OAuth 2.0 tokens and client-based OAuth 2.0 tokens. When you enable macaroons, AM will issue one of the following:

  • CTS-based macaroon tokens: the access token is stored in the CTS, and macaroons are the tokens issued to clients, where the identifier of the Macaroon is the pointer to the access token in the CTS.

  • Client-based macaroon tokens: the access token is a signed and/or encrypted JWT, which is then wrapped in a Macaroon. Note that the resulting size of the token may impact your deployment. If client storage is limited, such as when using browser cookies, the token may be too large to store. Token size may also impact network performance.

Enable macaroons

Follow these steps to enable macaroons in the OAuth 2.0 provider service:

  1. In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider.

  2. On the Core tab, enable Use Macaroon Access and Refresh Tokens.

  3. On the Advanced tab, select the Macaroon Token Format.

    It is recommended that you use the default V2. Configuring macaroons to use the older token format V1 is much less efficient. It should only be used when compatibility with older macaroon libaries is required.

  4. Set the OAuth2 Token Signing Algorithm to HS256, or higher.

  5. Save your changes.

OAuth 2.0 grant flows

This section describes the OAuth 2.0 flows that AM supports, and also provides the information required to implement them. All the examples assume the realm is configured for CTS-based tokens, however, the examples also apply to client-based tokens.

You should decide which flow is best for your environment based on the application that will be the OAuth 2.0 client. The following table provides an overview of the flows AM supports and when they should be used:

Table 3. Deciding Which Flow to Use Depending on the OAuth 2.0 Client
Client type Which grant to use? Description

The client is a web application running on a server. For example, a .war application.

(RFC 6749) The authorization server uses the user-agent, for example, the resource owner’s browser, to transport a code that is later exchanged for an access token.

The client is a native application or a single-page application (SPA). For example, a desktop, a mobile application, or a JavaScript application.

Authorization code with PKCE (RFC 6749, RFC 7636) The authorization server uses the user-agent, for example, the resource owner’s browser, to transport a code that is later exchanged for an access token.

Since the client does not communicate securely with the authorization server, the code may be intercepted by malicious users. The implementation of the Proof Key for Code Exchange (PKCE) standard mitigates against those attacks.

The client is a web application, a native application, or a SPA, that needs to make complex and highly secure authorization requests.

(RFC 9126) Clients can push the payload of an authorization request directly to the authorization server without exposing sensitive request data to the browser. The server provides them with a request URI that is used to secure a subsequent authorization request.

The client is a SPA. For example, a JavaScript application.

(RFC 6749) The authorization server gives the access token to the user-agent so it can forward the token to the client. Therefore, the access token might be exposed to the user and other applications.

For security purposes, you should use the authorization code grant with PKCE when possible.

The client is trusted with the resource owner credentials. For example, the resource owner’s operating system.

(RFC 6749) The resource owner provides their credentials to the client, which uses them to obtain an access token from the authorization server.

This flow should only be used if other flows are not available.

The client is the resource owner, or the client does not act on behalf of the resource owner.

(RFC 6749) Similar to the resource owner password credentials grant type, but the resource owner is not part of the flow and the client accesses information relevant to itself.

The client is an input-constrained device. For example, a TV set.

Device flow (RFC 8628) The resource owner authorizes the client to access protected resources on their behalf by using a different user-agent and entering a code displayed on the client device.

The client is an input-constrained device that can generate a PKCE challenge.

(AM-only, based on RFC 8628 and RFC 7636) The resource owner authorizes the client to access protected resources on their behalf by using a different user-agent and entering a code displayed on the client device.

Since the client does not communicate securely with the authorization server, the code may be intercepted by malicious users. The implementation of the Proof Key for Code Exchange (PKCE) standard mitigates against those attacks.

The client has a SAML v2.0 trust relationship with the resource owner. For example, an application in an environment where a SAML v2.0 ecosystem coexists with an OAuth 2.0 one.

(RFC 7522) The client uses the resource owner’s SAML v2.0 assertion to obtain an access token from the authorization server without interacting with the resource owner again.

The client has a trust relationship with the resource owner that is specified as a JWT. For example, an application in an environment where a non-SAML v2.0 identity ecosystem coexists with an OAuth 2.0 one.

AM supports associating a confirmation key with an access token to support proof-of-possession interactions. For more information, see JWK-based proof-of-possession.

Authorization code grant

The authorization code grant is a two-step interactive process used when the client, for example, a Java application running on a server, requires access to protected resources.

The authorization code grant is the most secure of all the OAuth 2.0 grants for the following reasons:

  • It is a two-step process. The user must authenticate and authorize the client to see the resources and the authorization server must validate the code again before issuing the access token.

  • The authorization server delivers the access token directly to the client, usually over HTTPS. The client secret is never exposed publicly, which protects confidential clients.

OAuth 2.0 authorization code grant flow
Figure 8. OAuth 2.0 authorization code grant flow
Authorization code grant flow explained
  1. The client, usually a web-based service, receives a request to access a protected resource. To access the resources, the client requires authorization from the resource owner.

  2. The client redirects the resource owner’s user-agent to the authorization server.

  3. The authorization server authenticates the resource owner, confirms resource access, and gathers consent if not previously saved.

  4. The authorization server redirects the resource owner’s user agent to the client.

  5. During the redirection process, the authorization server appends an authorization code.

  6. The client receives the authorization code and authenticates to the authorization server to exchange the code for an access token.

    Note that this example assumes a confidential client. Public clients are not required to authenticate.

  7. If the authorization code is valid, the authorization server returns an access token (and a refresh token, if configured) to the client.

  8. The client requests access to the protected resources from the resource server.

  9. The resource server contacts the authorization server to validate the access token.

  10. The authorization server validates the token and responds to the resource server.

  11. If the token is valid, the resource server allows the client to access the protected resources.

Perform the steps in the following procedures to obtain an authorization code and exchange it for an access token:

Get an authorization code using a browser

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server. Ensure that the Authorization Code grant type is configured in the Grant Types field.

    For more information, see Authorization server configuration.

  • A confidential client called myClient is registered in AM with the following configuration:

    • Client secret: forgerock

    • Scopes: write

    • Response Types: code

    • Grant Types: Authorization Code

For more information, see Client registration.

Perform the steps in this procedure to obtain an authorization code using a browser:

  1. The client redirects the resource owner’s user-agent to the authorization server’s authorization endpoint specifying, at least, the following form parameters:

    • client_id=your-client-id

    • response_type=code

    • redirect_uri=your-redirect-id

    For information about the parameters supported by the /oauth2/authorize endpoint, see /oauth2/authorize.

    You must specify the realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/authorize.

    For example:

    https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/authorize \
    ?client_id=myClient \
    &response_type=code \
    &scope=write \
    &state=abc123 \
    &redirect_uri=https://www.example.com:443/callback

    Note that the URL is split and spaces have been added for readability purposes and that the scope and state parameters have been included. Scopes are not required, since they can be configured by default in the authorization server and the client, and have been added only as an example. The state parameter is added to protect against CSRF attacks.

  2. The resource owner authenticates to the authorization server, for example, using the credentials of the demo user. In this case, they log in using the default chain or tree configured for the realm.

    After logging in, the authorization server presents the AM consent screen:

    The OAuth 2.0 AM user interface consent screen requesting access to the write scope.
    Figure 9. OAuth 2.0 Consent Screen
  3. The resource owner selects the Allow button to grant consent for the write scope.

    The authorization server redirects the resource owner to the URL specified in the redirect_uri parameter.

  4. Inspect the URL in the browser.

    It contains a code parameter with the authorization code the authorization server has issued.

    For example:

    http://www.example.com/?code=g5B3qZ8rWzKIU2xodV_kkSIk0F4&scope=write&iss=https%3A%2F%2Fopenam.example.com%3A8443%2Fopenam%2Foauth2&state=abc123&client_id=myClient
  5. The client performs the steps in Exchange an authorization code for an access token to exchange the authorization code for an access token.

Get an authorization code without using a browser

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server. Ensure that:

    • The code plugin is configured in the Response Type Plugins field.

    • The Authorization Code grant type is configured in the Grant Types field.

    For more information, see Authorization server configuration.

  • A confidential client called myClient is registered in AM with the following configuration:

    • Client secret: forgerock

    • Scopes: write

    • Response Types: code

    • Grant Types: Authorization Code

For more information, see Client registration.

Perform the steps in this procedure to obtain an authorization code without using a browser:

  1. The resource owner logs in to the authorization server, for example, using the credentials of the demo user.

    For example:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  2. The client makes a POST call to the authorization server’s authorization endpoint, specifying the SSO token of the demo in a cookie and, at least, the following parameters:

    • client_id=your-client-id

    • response_type=code

    • redirect_uri=your-redirect-uri

    • decision=allow

    • csrf=demo-user-SSO-token

    For information about the parameters supported by the /oauth2/authorize endpoint, see /oauth2/authorize.

    You must specify the realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/authorize.

    For example:

    $ curl --dump-header - \
    --request POST \
    --Cookie "<session-cookie-name>=AQIC5wM…​TU3OQ*" \
    --data "scope=write" \
    --data "response_type=code" \
    --data "client_id=myClient" \
    --data "csrf=AQIC5wM…​TU3OQ*" \
    --data "redirect_uri=https://www.example.com:443/callback" \
    --data "state=abc123" \
    --data "decision=allow" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/authorize"

    Note that the scope and the state parameters have been included. Scopes are not required, since they can be configured by default in the authorization server and the client, and have been added only as an example. The state parameter is added to protect against CSRF attacks.

    If the authorization server is able to authenticate the user and the client, it returns an HTTP 302 response with the authorization code appended to the redirection URL:

    HTTP/1.1 302 Found
    Server: Apache-Coyote/1.1
    X-Frame-Options: SAMEORIGIN
    Pragma: no-cache
    Cache-Control: no-store
    Date: Mon, 30 Jul 2018 11:42:37 GMT
    Accept-Ranges: bytes
    Location: https://www.example.com:443/callback?code=g5B3qZ8rWzKIU2xodV_kkSIk0F4&scope=write&iss=https%3A%2F%2Fopenam.example.com%3A8443%2Fopenam%2Foauth2&state=abc123&client_id=myClient
    Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
    Content-Length: 0
  3. Perform the steps in Exchange an authorization code for an access token to exchange the authorization code for an access token.

Exchange an authorization code for an access token

Perform the steps in the following procedure to exchange an authorization code for an access token:

  1. Ensure the client has obtained an authorization code by performing the steps in either Get an authorization code using a browser or Get an authorization code without using a browser.

  2. The client creates a POST request to the token endpoint in the authorization server specifying, at least, the following parameters:

    • grant_type=authorization_code

    • code=your-authorization-code

    • redirect_uri=your-redirect-uri

    For information about the parameters supported by the /oauth2/access_token endpoint, see /oauth2/access_token.

    Confidential clients can authenticate to the OAuth 2.0 endpoints in several ways. This example uses the following form parameters:

    • client_id=your-client-id

    • client_secret=your-client-secret

    For more information, see OAuth 2.0 client authentication.

    You must specify the realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/access_token.

    For example:

    $ curl --request POST \
    --data "grant_type=authorization_code" \
    --data "code=g5B3qZ8rWzKIU2xodV_kkSIk0F4" \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data "redirect_uri=https://www.example.com:443/callback" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"

    The client_id and the redirection_uri parameters specified in this call must match those used as part of the authorization code request, or the authorization server will not validate the code.

    The authorization server returns an access token in the access_token property. For example:

    {
      "access_token": "sbQZuveFumUDV5R1vVBl6QAGNB8",
      "scope": "write",
      "token_type": "Bearer",
      "expires_in": 3599
    }

    The authorization server can also issue refresh tokens at the same time the access tokens are issued. For more information, see Refresh tokens.

Authorization code grant with PKCE

The authorization code grant, when combined with the PKCE standard (RFC 7636), is used when the client, usually a mobile or a JavaScript application, requires access to protected resources.

The flow is similar to the regular authorization code grant type, but the client must generate a code that will be part of the communication between the client and the authorization server. This code mitigates against interception attacks performed by malicious users.

Since communication between the client and the authorization server is not secure, clients are usually public so their secrets do not get compromised. Also, browser-based clients making OAuth 2.0 requests to different domains must implement Cross-Origin Resource Sharing (CORS) calls to access OAuth 2.0 resources in different domains.

The PKCE flow adds three parameters on top of those used for the authorization code grant:

  • code_verifier (form parameter). Contains a random string that correlates the authorization request to the token request.

  • code_challenge (query parameter). Contains a string derived from the code verifier that is sent in the authorization request and that needs to be verified later with the code verifier.

  • code_challenge_method (query parameter). Contains the method used to derive the code challenge.

OAuth 2.0 authorization code grant with PKCE flow
Figure 10. OAuth 2.0 authorization code grant with PKCE flow
Authorization code grant with PKCE flow explained
  1. The client receives a request to access a protected resource. To access the resources, the client requires authorization from the resource owner. When using the PKCE standard, the client must generate a unique code and a way to verify it, and append the code to the request for the authorization code.

  2. The client redirects the resource owner’s user-agent to the authorization server.

  3. The authorization server authenticates the resource owner, confirms resource access, and gathers consent if not previously saved.

  4. If the resource owner’s credentials are valid, the authorization server stores the code challenge and redirects the resource owner’s user agent to the redirection URI.

  5. During the redirection process, the authorization server appends an authorization code to the request to the client.

  6. The client receives the authorization code and calls the authorization server’s token endpoint to exchange the authorization code for an access token appending the verification code to the request.

  7. The authorization server verifies the code stored in memory using the validation code. It also verifies the authorization code. If both codes are valid, the authorization server returns an access token (and a refresh token, if configured) to the client.

  8. The client requests access to the protected resources from the resource server.

  9. The resource server contacts the authorization server to validate the access token.

  10. The authorization server validates the token and responds to the resource server.

  11. If the token is valid, the resource server allows the client to access the protected resources.

Perform the steps in the following procedures to obtain an authorization code and exchange it for an access token:

Generate a code verifier and a code challenge

The client application must be able to generate a code verifier and a code challenge. For details, see the PKCE standard (RFC 7636). The information contained in this procedure is for example purposes only:

  1. The client generates the code challenge and the code verifier. Creating the challenge using a SHA-256 algorithm is mandatory if the client supports it, as per the RFC 7636 standard.

    The following is an example of a code verifier and code challenge written in JavaScript:

    function base64URLEncode(words) {
       return CryptoJS.enc.Base64.stringify(words)
       .replace(/\+/g, '-')
       .replace(/\//g, '_')
       .replace(/=/g, '');
    }
    var verifier = base64URLEncode(CryptoJS.lib.WordArray.random(50));
    var challenge = base64URLEncode(CryptoJS.SHA256(verifier));

    This example generates values such as ZpJiIM_G0SE9WlxzS69Cq0mQh8uyFaeEbILlW8tHs62SmEE6n7Nke0XJGx_F4OduTI4 for the code verifier and j3wKnK2Fa_mc2tgdqa6GtUfCYjdWSA5S23JKTTtPF8Y for the code challenge. These values will be used in subsequent procedures.

    The client is now ready to request an authorization code.

  2. The client performs the steps in one of the following procedures to request an authorization code:

Get an authorization code using a browser

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server. Ensure that the Authorization Code grant type is configured in the Grant Types field.

    The Code Verifier Parameter Required setting (Realms > Realm Name > Services > OAuth2 Provider > Advanced) specifies whether AM requires clients to include a code verifier in their calls. However, if a client makes a call to AM with the code_challenge parameter, AM will honor the code exchange regardless of the Code Verifier Parameter Required value. For more information, see Authorization server configuration.

  • A public client called myClient is registered in AM with the following configuration:

    • Scopes: write

    • Response Types: code

    • Grant Types: Authorization Code

For more information, see Client registration.

Perform the steps in this procedure to obtain an authorization code using a browser:

  1. The client redirects the resource owner’s user-agent to the authorization server’s authorization endpoint specifying, at least, the following query parameters:

    • client_id=your-client-id

    • response_type=code

    • redirect_uri=your-redirect-uri

    • code_challenge=your-code-challenge

    • code_challenge_method=S256

    For information about the parameters supported by the /oauth2/authorize endpoint, see /oauth2/authorize.

    You must specify the realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/authorize.

    For example:

    https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/authorize \
    ?client_id=myClient \
    &response_type=code \
    &scope=write \
    &redirect_uri=https://www.example.com:443/callback \
    &code_challenge=j3wKnK2Fa_mc2tgdqa6GtUfCYjdWSA5S23JKTTtPF8Y \
    &code_challenge_method=S256 \
    &state=abc123

    Note that the URL is split and spaces have been added for readability purposes and that the scope and state parameters have been included. Scopes are not required, since they can be configured by default in the authorization server and the client, and have been added only as an example. The state parameter is added to protect against CSRF attacks.

  2. The resource owner authenticates to the authorization server, for example, using the credentials of the demo user. In this case, they log in using the default chain or tree configured for the realm.

    After logging in, the authorization server presents the AM consent screen:

    The OAuth 2.0 AM user interface consent screen requesting access to the write scope.
    Figure 11. OAuth 2.0 Consent Screen
  3. The resource owner selects the Allow button to grant consent for the write scope.

    The authorization server redirects the resource owner to the URL specified in the redirect_uri parameter.

  4. Inspect the URL in the browser.

    It contains a code parameter with the authorization code the authorization server has issued.

    For example:

    http://www.example.com/?code=ZNSDo8LrsI2w-6NOCYKQgvDPqtg&scope=write&iss=https%3A%2F%2Fopenam.example.com%3A8443%2Fopenam%2Foauth2&state=abc123&client_id=myClient
  5. The client performs the steps in Exchange an authorization code for an access token to exchange the authorization code for an access token.

Get an authorization code without using a browser

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server. Ensure that the Authorization Code grant type is configured in the Grant Types field.

    The Code Verifier Parameter Required setting (Realms > Realm Name > Services > OAuth2 Provider > Advanced) specifies whether AM requires clients to include a code verifier in their calls. However, if a client makes a call to AM with the code_challenge parameter, AM will honor the code exchange regardless of the Code Verifier Parameter Required value. For more information, see Authorization server configuration.

  • A public client called myClient is registered in AM with the following configuration:

    • Scopes: write

    • Response Types: code

    • Grant Types: Authorization Code

For more information, see Client registration.

Perform the steps in this procedure to obtain an authorization code:

  1. The resource owner logs in to the authorization server, for example, using the credentials of the demo user.

    For example:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  2. The client makes a POST call to the authorization server’s authorization endpoint specifying in a cookie SSO token of the demo and, at least, the following parameters:

    • client_id=your-client-id

    • response_type=code

    • redirect_uri=your-redirect-uri

    • decision=allow

    • csrf=demo-user-SSO-token

    • code_challenge=your-code-challenge

    • code_challenge_method=S256

    For information about the parameters supported by the /oauth2/authorize endpoint, see /oauth2/authorize.

    You must specify the realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/authorize.

    For example:

    $ curl --dump-header - \
    --request POST \
    --Cookie "<session-cookie-name>=AQIC5wM…​TU3OQ*" \
    --data "redirect_uri=https://www.example.com:443/callback" \
    --data "scope=write" \
    --data "response_type=code" \
    --data "client_id=myClient" \
    --data "csrf=AQIC5wM…​TU3OQ*" \
    --data "state=abc123" \
    --data "decision=allow" \
    --data "code_challenge=j3wKnK2Fa_mc2tgdqa6GtUfCYjdWSA5S23JKTTtPF8Y" \
    --data "code_challenge_method=S256" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/authorize"

    Note that the scope and the state parameters have been included. Scopes are not required, since they can be configured by default in the authorization server and the client, and have been added only as an example. The state parameter is added to protect against CSRF attacks.

    If the authorization server is able to authenticate the user and the client, it returns an HTTP 302 response with the authorization code appended to the redirection URL:

    HTTP/1.1 302 Found
    Server: Apache-Coyote/1.1
    X-Frame-Options: SAMEORIGIN
    Pragma: no-cache
    Cache-Control: no-store
    Date: Mon, 30 Jul 2018 11:42:37 GMT
    Accept-Ranges: bytes
    Location: http://www.example.com?code=g5B3qZ8rWzKIU2xodV_kkSIk0F4&scope=write&iss=https%3A%2F%2Fopenam.example.com%3A8443%2Fopenam%2Foauth2&state=abc123&client_id=myClient
    Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
    Content-Length: 0
  3. Perform the steps in Exchange an authorization code for an access token to exchange the authorization code for an access token.

Exchange an authorization code for an access token

Perform the steps in the following procedure to exchange an authorization code for an access token:

  1. Ensure the client has obtained an authorization code by performing the steps in either:

  2. The client creates a POST request to the token endpoint in the authorization server specifying, at least, the following parameters:

    • grant_type=authorization_code

    • code=your-authorization-code

    • client_id=your-client-id

    • redirect_uri=your-redirect-uri

    • code_verifier=your-code-verifier

    For information about the parameters supported by the /oauth2/access_token endpoint, see /oauth2/access_token. For information about private client authentication methods, see OAuth 2.0 client authentication.

    For example:

    $ curl --request POST \
    --data "grant_type=authorization_code" \
    --data "code=g5B3qZ8rWzKIU2xodV_kkSIk0F4" \
    --data "client_id=myClient" \
    --data "redirect_uri=https://www.example.com:443/callback" \
    --data "code_verifier=ZpJiIM_G0SE9WlxzS69Cq0mQh8uyFaeEbILlW8tHs62SmEE6n7Nke0XJGx_F4OduTI4" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"

    The client_id and the redirection_uri parameters specified in this call must match those used as part of the authorization code request, or the authorization server will not validate the code.

    The authorization server returns an access token in the access_token property. For example:

    {
      "access_token": "sbQZuveFumUDV5R1vVBl6QAGNB8",
      "scope": "write",
      "token_type": "Bearer",
      "expires_in": 3599
    }

    The authorization server can also issue refresh tokens at the same time the access tokens are issued. For more information, see Refresh tokens.

Authorization code grant with PAR

The pushed authorization request (PAR) endpoint provides enhanced security and cryptographic integrity when used with the Authorization Code grant flow, and optionally, in conjunction with PKCE.

PAR lets the authorization server authenticate the client before making an authorization request to ensure early detection of invalid or illegal requests.

To further protect authorization details when passing through third-party applications, clients can use JWT-based request objects as defined by RFC9101, to wrap confidential and potentially complex request parameters.

In response to this pre-authorization backchannel request, the client receives a request URI that is used to reference the payload data in subsequent interactions with the server.

The use of PAR is optional by default. To force clients to use the PAR endpoint to initiate authorization requests, configure the OAuth 2.0 provider advanced settings. To configure the setting for a particular client only, see the client settings.

OAuth 2.0 Authorization code grant flow
Figure 12. OAuth 2.0 Authorization code grant flow
Authorization code grant flow with PAR explained
  1. The client pushes a request to the PAR endpoint, providing both client and request details.

  2. AM validates both client and request, and if successful, returns a request URI as a reference to the request payload and an expiry period for the request URI.

  3. The client receives a request to access a protected resource. To access the resources, the client requires authorization from the resource owner.

  4. The client redirects the resource owner’s user-agent to the authorization server.

  5. The authorization server authenticates the resource owner, confirms resource access, and gathers consent if not previously saved.

  6. The client requests an authorization code, typically through a web browser, by passing in the request_uri and client_id.

  7. The client_id is validated against the request, and if successful, the authorization code is returned to the client.

  8. The client authenticates to the authorization server using the received code in exchange for an access token.

    Note that this example assumes a confidential client. Public clients are not required to authenticate.

  9. If the authorization code is valid, the authorization server returns an access token (and a refresh token, if configured) to the client.

  10. The client requests access to the protected resources from the resource server.

  11. The resource server contacts the authorization server to validate the access token.

  12. The authorization server validates the token and responds to the resource server.

  13. If the token is valid, the resource server allows the client to access the protected resources.

Perform the steps in the following procedures to obtain a PAR request URI and an authorization code to exchange for an access token:

Get a PAR request URI

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server. Ensure that:

    • The code plugin is configured in the Response Type Plugins field.

    • The Authorization Code grant type is configured in the Grant Types field.

    • The PAR Request URI Lifetime attribute is set to a value sufficient to cover the duration of the PAR request.

      For more information, see the configuration for OAuth2 Provider.

  • A confidential client called myClient is registered in AM with the following configuration:

    • Client secret: forgerock

    • Scopes: write

    • Response Types: code

    • Grant Types: Authorization Code

For more information, see Client registration.

Perform the steps in this procedure to obtain a request uri:

  1. The resource owner logs in to the authorization server, for example, using the credentials of the demo user.

    For example:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  2. The client makes a POST request to the authorization server’s PAR endpoint. Specify parameters directly in the request body, or for large or sensitive data, AM supports the JWT-Secured Authorization Request (JAR) standard for PAR, which lets you wrap parameters in a signed and encrypted JWT.

    Example parameters with a JWT:

    • client_id=your-client-id

    • client_secret=your-client-secret

    • request=encoded signed JWT value

    Example parameters without a JWT:

    • client_id=your-client-id

    • client_secret=your-client-secret

    • redirect_uri=your-redirect-id

    • scope=write

    • response_type=code

    • code_challenge=QR1D-7w1-rOQvlFe1CeqZigqaIpmZXatDMVvZ50o

    • code_challenge_method=S256

    For information about the parameters supported by the /oauth2/par endpoint, see /oauth2/par.

    Example PAR request with a JWT:

    $ curl --request POST \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data "request=eyJhbGciOiJIUzI1NiJ…​mnRTwgPGTqkp5UBTVWaA_CifxWx1ikcZofOas" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/par"

    Example PAR request without a JWT:

    $ curl --request POST \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data "response_type=code" \
    --data "scope=write" \
    --data "code_challenge=QR1D-7w1-rOQvlFe1CeqZigqaIpmZXatDMVvZ50o" \
    --data "code_challenge_method=S256" \
    --data "redirect_uri=https://www.example.com:443" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/par"

    On success, AM returns the following JSON:

    ${
      "request_uri": "C2c3yhu2IApAELttmZtfPNPQaIJxvTCHk",
      "expires_in": 90
    }
    1. request_uri: A reference to the PAR request payload.

    2. expires_in: The validity period of the request URI in seconds.

Get an authorization code using a browser

Perform the steps in this procedure to obtain an authorization code using a browser:

  1. Ensure the client has retrieved a request URI by following the steps described in Get a PAR request URI.

  2. The client redirects the resource owner’s user-agent to the authorization server’s authorization endpoint specifying, at least, the following form parameters:

    • client_id=your-client-id

    • response_type=code

    • redirect_uri=your-redirect-id

    • request_uri=the-PAR-request-uri

    For information about the parameters supported by the /oauth2/authorize endpoint, see /oauth2/authorize.

    For example:

    https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/authorize \
    ?client_id=myClient \
    &request_uri=C2c3yhu2IApAELttmZtfPNPQaIJxvTCHk
    &response_type=code \
    &scope=write \
    &state=abc123 \
    &redirect_uri=https://www.example.com:443/callback

    Note that the URL is split and spaces have been added for readability purposes and that the scope and state parameters have been included. Scopes are not required, since they can be configured by default in the authorization server and the client, and have been added only as an example. The state parameter is added to protect against CSRF attacks.

  3. The resource owner authenticates to the authorization server, for example, using the credentials of the demo user. In this case, they log in using the default chain or tree configured for the realm.

  4. On a successful login, the authorization server presents the AM consent screen. Click Allow to consent.

    The authorization server redirects the resource owner to the URL specified in the redirect_uri parameter.

  5. Inspect the URL in the browser.

    It contains a code parameter with the authorization code the authorization server has issued.

    For example:

    http://www.example.com/?code=g5B3qZ8rWzKIU2xodV_kkSIk0F4&scope=write&iss=https%3A%2F%2Ftenant-name.forgeblocks.com%3A8443%am%2Foauth2&state=abc123&client_id=myClient
  6. The client performs the steps in Exchange an authorization code for an access token to exchange the authorization code for an access token.

Get an authorization code using REST

Perform the steps in this procedure to obtain an authorization code without a browser.

  1. Ensure the client has retrieved a request URI by following the steps described in Get a PAR request URI.

  2. The resource owner logs in to the authorization server, for example, using the credentials of the demo user.

    For example:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  3. The client makes a POST call to the authorization server’s authorization endpoint, specifying the SSO token of the demo in a cookie and, at least, the following parameters:

    • client_id=your-client-id

    • request_uri=the-PAR-request-uri

    • response_type=code

    • redirect_uri=your-redirect-uri

    • decision=allow

    • csrf=demo-user-SSO-token

    For information about the parameters supported by the /oauth2/authorize endpoint, see /oauth2/authorize.

    For example:

    $ curl --dump-header - \
    --request POST \
    --Cookie "iPlanetDirectoryPro=AQIC5wM…​TU3OQ*" \
    --data "request_uri=C2c3yhu2IApAELttmZtfPNPQaIJxvTCHk" \
    --data "client_id=myClient" \
    --data "scope=write" \
    --data "response_type=code" \
    --data "csrf=AQIC5wM…​TU3OQ*" \
    --data "redirect_uri=https://www.example.com:443/callback" \
    --data "state=abc123" \
    --data "decision=allow" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/authorize"

    Note that the scope and the state parameters have been included. Scopes are not required, since they can be configured by default in the authorization server and the client, and have been added only as an example. The state parameter is added to protect against CSRF attacks.

    If the authorization server is able to authenticate the user and the client, it returns an HTTP 302 response with the authorization code appended to the redirection URL:

    HTTP/1.1 302 Found
    Server: Apache-Coyote/1.1
    X-Frame-Options: SAMEORIGIN
    Pragma: no-cache
    Cache-Control: no-store
    Date: Mon, 30 Jul 2018 11:42:37 GMT
    Accept-Ranges: bytes
    Location: https://www.example.com:443/callback?code=g5B3qZ8rWzKIU2xodV_kkSIk0F4&scope=write&iss=https%3A%2F%2Fopenam.example.com%3A8443%2Fopenam%2Foauth2&state=abc123&client_id=myClient
    Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
    Content-Length: 0
  4. Perform the steps in Exchange an authorization code for an access token to get an access token.

Exchange an authorization code for an access token

Perform the steps in the following procedure to exchange an authorization code for an access token:

  1. Ensure the client has obtained an authorization code by performing the steps in either Get an authorization code using a browser or Get an authorization code using REST.

  2. The client creates a POST request to the token endpoint in the authorization server specifying, at least, the following parameters:

    • grant_type=authorization_code

    • code=your-authorization-code

    • redirect_uri=your-redirect-uri

    For information about the parameters supported by the /oauth2/access_token endpoint, see /oauth2/access_token.

    Confidential clients can authenticate to the OAuth 2.0 endpoints in several ways. This example uses the following form parameters:

    • client_id=your-client-id

    • client_secret=your-client-secret

    For more information, see OAuth 2.0 client authentication.

    For example:

    $ curl --request POST \
    --data "grant_type=authorization_code" \
    --data "code=g5B3qZ8rWzKIU2xodV_kkSIk0F4" \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data "redirect_uri=https://www.example.com:443/callback" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"

    The client_id and the redirect_uri parameters specified in this call must match those used as part of the authorization code request, or the authorization server will not validate the code.

    The authorization server returns an access token in the access_token property. For example:

    {
      "access_token": "sbQZuveFumUDV5R1vVBl6QAGNB8",
      "scope": "write",
      "token_type": "Bearer",
      "expires_in": 3599
    }

    The authorization server can also issue refresh tokens at the same time the access tokens are issued. For more information, see Refresh tokens.

Implicit grant

Endpoints

The implicit grant is designed for public clients that run inside the resource owner’s user-agent, for example, JavaScript applications.

Since applications running in the user-agent are considered less trusted than applications running in servers, the authorization server will never issue refresh tokens in this flow. Also, you must consider the security impact of cross-site scripting (XSS) attacks that could leak the access token to other systems, and implement cross-origin resource sharing (CORS) to make OAuth 2.0 requests to different domains.

Due to the security implications of this flow, it is recommended to use the authorization code grant with PKCE flow whenever possible.

OAuth 2.0 Implicit Grant Flow
Figure 13. OAuth 2.0 Implicit Grant Flow
Implicit grant flow explained
  1. The client, usually a single-page application (SPA), receives a request to access a protected resource. To access the resources, the client requires authorization from the resource owner.

  2. The client redirects the resource owner’s user-agent or opens a new frame to the AM authorization service.

  3. The authorization server authenticates the resource owner, confirms resource access, and gathers consent if not previously saved.

  4. If the resource owner’s credentials are valid, the authorization server returns the access token to the user-agent as part of the redirection URI.

  5. Now, the client must extract the access token from the URI. In this example, the user-agent follows the redirection to the web-hosted server that contains the protected resources without the access token…​

  6. …​And the web-hosted server returns a web page with an embedded script to extract the access token from the URI.

    In another possible scenario, the redirection URI is a dummy URI in the client, and the client already has the logic in itself to extract the access token.

  7. The user-agent executes the script and retrieves the access token.

  8. The user-agent returns the access token to the client.

  9. The client requests access to the protected resources presenting the access token to the resource server.

  10. The resource server contacts the authorization server to validate the access token.

  11. The authorization server validates the token and responds to the resource server.

  12. If the token is valid, the resource server allows the client to access the protected resources.

Perform the steps in the following procedures to obtain an access token:

Get an access token using a browser

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server. Ensure that:

    • The token plugin is configured in the Response Type Plugins field.

    • The Implicit Grant grant type is configured in the Grant Types field.

    For more information, see Authorization server configuration.

  • A public client called myClient is registered in AM with the following configuration:

    • Scopes: write

    • Response Types: token

    • Grant Types: Implicit

For more information, see Client registration.

Perform the steps in this procedure to obtain an access token using the implicit grant:

  1. The client makes a GET call to the authorization server’s authorization endpoint specifying, at least, the following parameters:

    • client_id=your-client-id

    • response_type=token

    • redirect_uri=your-redirect-uri

    For information about the parameters supported by the /oauth2/authorize endpoint, see /oauth2/authorize.

    You must specify the realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/authorize.

    For example:

    https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/authorize \
    ?client_id=myClient \
    &response_type=token \
    &scope=write \
    &redirect_uri=https://www.example.com:443/callback \
    &state=abc123

    Note that the URL is split for readability purposes and that the scope and state parameters have been included. Scopes are not required, since they can be configured by default in the authorization server and the client, and have been added only as an example. The state parameter is added to protect against CSRF attacks. Also, the redirection URI was not specified, and the URI defined in the client profile is used by default.

  2. The resource owner logs in to the authorization server, for example, using the credentials of the demo user.

    In this case, they log in using the default chain or tree configured for the realm.

    After logging in, the authorization server presents the AM user interface consent screen:

    The OAuth 2.0 AM user interface consent screen requesting access to a scope.
    Figure 14. OAuth 2.0 Consent Screen
  3. The resource owner selects the Allow button to grant consent for the write scope.

    The authorization server redirects the resource owner to the URL specified in the redirect_uri parameter.

  4. Inspect the URL in the browser.

    It contains an access_token parameter with the access token the authorization server has issued.

    For example:

    https://www.example.com:443/callback#access_token=1i5IfaebiLnpyxFM4mcTSZSegb4&scope=write&redirect_uri%3Dhttps%3A%2F%2Fwww.example.com%3A8443%2Fcallback&iss=https%3A%2F%2Fopenam.example.com%3A8443%2Fopenam%2Foauth2&state=abc123&client_id=myClient

Get an access token without using a browser

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server. Ensure that:

    • The token plugin is configured in the Response Type Plugins field.

    • The Implicit Grant grant type is configured in the Grant Types field.

    For more information, see Authorization server configuration.

  • A public client called myClient is registered in AM with the following configuration:

    • Scopes: write

    • Response Types: token

    • Grant Types: Implicit

For more information, see Client registration.

Perform the steps in this procedure to obtain an access token using the Implicit grant:

  1. The resource owner authenticates to the authorization server, for example, using the credentials of the demo user.

    For example:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  2. The client makes a POST call to the authorization server’s authorization endpoint, specifying the SSO token of the demo in a cookie and, at least, the following parameters:

    • client_id=your-client-id

    • response_type=token

    • decision=allow

    • csrf=demo-user-SSO-token

    • redirect_uri=your-redirect-uri

    For information about the parameters supported by the /oauth2/authorize endpoint, see /oauth2/authorize.

    You must specify the realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/authorize.

    For example:

    $ curl --dump-header - \
    --Cookie "<session-cookie-name>=AQIC5wM…​TU3OQ*" \
    --request POST \
    --data "client_id=myClient" \
    --data "response_type=token" \
    --data "scope=write" \
    --data "state=123abc" \
    --data "decision=allow" \
    --data "csrf=AQIC5wM…​TU3OQ*" \
    --data "redirect_uri=https://www.example.com:443/callback" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/authorize"

    Note that the scope and state parameters have been included. Scopes are not required, since they can be configured by default in the authorization server and the client, and have been added only as an example. The state parameter is added to protect against CSRF attacks.

    If the authorization server is able to authenticate the user, it returns an HTTP 302 response with the access token appended to the redirection URI:

    1.1 302 Found
    Server: Apache-Coyote/1.1
    X-Frame-Options: SAMEORIGIN
    Pragma: no-cache
    Cache-Control: no-store
    Date: Wed, 22 Aug 2018 11:19:54 GMT
    Accept-Ranges: bytes
    Location: https://www.example.com:443/callback#access_token=PAsODWCvnb5W8uuBT12H62Rvmro&scope=write&redirect_uri%3Dhttps%3A%2F%2Fwww.example.com%3A8443%2Fcallback&iss=https%3A%2F%2Fopenam.example.com%3A8443%2Fopenam%2Foauth2&state=123abc&token_type=Bearer&expires_in=3599&client_id=myClient
    Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
    Content-Length: 0

    In this case, the redirection URI was not specified in the command, and the URI defined in the client profile is used by default.

Resource owner password credentials grant

The resource owner password credentials (ROPC) grant flow lets the client use the resource owner’s user name and password to get an access token.

Since the resource owner shares their credentials with the client, this flow is deemed the most insecure of the OAuth 2.0 flows. The resource owner’s credentials can potentially be leaked or abused by the client application, and the resource owner has no control over the authorization process.

You should implement the ROPC grant flow only if the resource owner has a trust relationship with the client (such as the device operating system, or a highly privileged application).

OAuth 2.0 Resource Owner Password Credentials Grant Flow
Figure 15. OAuth 2.0 Resource Owner Password Credentials Grant Flow
ROPC grant flow explained
  1. The resource owner provides the client with their username and password.

  2. The client sends the resource owner’s and its own credentials to the authorization server, which authenticates the credentials and authorizes the resource owner’s request.

  3. If the credentials are valid, the authorization server returns an access token to the client.

  4. The client requests access to the protected resources presenting the access token to the resource server.

  5. The resource server contacts the authorization server to validate the access token.

  6. The authorization server validates the token and responds to the resource server.

  7. If the token is valid, the resource server allows the client to access the protected resources.

Perform the following procedure to obtain an access token:

Obtain an access token using the ROPC grant flow

This procedure assumes the following configuration:

  • An authentication service that is able to authenticate a username and password combination, without requiring any UI-based interaction from the resource owner, is available.

    For example, the Login journey.

    Specify the tree by using one or more of the methods below. AM checks for the configured value in the following order, using the first value found:

    1. For a specific access token REST request.

      Set the auth_chain parameter.

    2. Individually for a realm, overriding the realm-level setting below.

      Navigate to Realms > Realm Name > Services > OAuth2 Provider > Advanced, and set the Password Grant Authentication Service property.

    3. Individually for a realm.

      Navigate to Realms > Realm Name > Authentication > Settings > Core, and set the Organization Authentication Configuration property.

    4. Globally, for all realms.

      Navigate to Configure > Authentication > Core Attributes > Core, and set the Organization Authentication Configuration property.

  • AM is configured as an OAuth 2.0 authorization server. Ensure that:

    • The Resource Owner Password Credentials grant type is configured in the Grant Types field.

    For more information, see Authorization server configuration.

  • A confidential client called myClient is registered in AM with the following configuration:

    • Client secret: forgerock

    • Scopes: write

    • Grant Types: Resource Owner Password Credentials

For more information, see Client registration.

Perform the following steps to obtain an access token using the ROPC grant flow:

  1. The resource owner provides their credentials to the client. This is done outside the scope of this procedure.

  2. The client creates a POST request to the authorization server’s token endpoint specifying, at least, the following parameters:

    • username=your-resource-owner-username

    • password=your-resource-owner-password

    • grant_type=password

      For information about the parameters supported by the /oauth2/access_token endpoint, see /oauth2/access_token.

      Confidential clients can authenticate to the OAuth 2.0 endpoints in several ways. This example uses the following form parameters:

    • client_id=your-client-id

    • client_secret=your-client-secret

    For more information, see OAuth 2.0 client authentication.

    You must specify the realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/access_token.

    For example:

    $ curl --request POST \
    --data "grant_type=password" \
    --data "username=demo" \
    --data "password=Ch4ng31t" \
    --data "scope=write" \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"

    Note that the scope parameter has been included. Scopes are not required, since they can be configured by default in the authorization server and the client, and have been added only as an example.

    The authorization server returns an access token in the access_token property. For example:

    {
      "access_token": "sbQZuveFumUDV5R1vVBl6QAGNB8",
      "scope": "write",
      "token_type": "Bearer",
      "expires_in": 3599
    }

    The authorization server can also issue refresh tokens at the same time the access tokens are issued. For more information, see Refresh tokens.

Client credentials grant

The client credentials grant is used when the client is also the resource owner and it is accessing its own data instead of acting in behalf of a user. For example, an application that needs access to a protected resource to retrieve its own data to perform a task, or update its configuration, would use the Client Credentials grant to acquire an access token.

The client credentials grant flow supports confidential clients only.

OAuth 2.0 client credentials grant flow
Figure 16. OAuth 2.0 client credentials grant flow
Client credentials flow explained
  1. The client sends its credentials to the authorization server to get authenticated, and requests an access token.

  2. If the client credentials are valid, the authorization server returns an access token to the client.

  3. The client requests access to the protected resources from the resource server.

  4. The resource server contacts the authorization server to validate the access token.

  5. The authorization server validates the token and responds to the resource server.

  6. If the token is valid, the resource server allows the client to access the protected resources.

Get an access token using the client credentials grant

Perform the steps in the following procedure to obtain an access token. This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server. Ensure that:

    • The Client Credentials grant type is configured in the Grant Types field.

    For more information, see Authorization server configuration.

  • A confidential client called myClient is registered in AM with the following configuration:

    • Client secret: forgerock

    • Scopes: write

    • Grant Types: Client Credentials

For more information, see Client registration.

  1. The client makes a POST call to the authorization server’s token endpoint specifying, at least, the following parameters:

    • grant_type=client_credentials

    For information about the parameters supported by the /oauth2/access_token endpoint, see /oauth2/access_token.

    Confidential clients can authenticate to the OAuth 2.0 endpoints in several ways. This example uses the following form parameters:

    • client_id=your-client-id

    • client_secret=your-client-secret

    For more information, see OAuth 2.0 client authentication.

    You must specify the realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/access_token.

    For example:

    $ curl --request POST \
    --data "grant_type=client_credentials" \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data "scope=write" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"

    Note that the scope parameter has been included. Scopes are not required, since they can be configured by default in the authorization server and the client, and have been added only as an example.

    The authorization server returns an access token in the access_token property. For example:

    {
      "access_token": "sbQZuveFumUDV5R1vVBl6QAGNB8",
      "scope": "write",
      "token_type": "Bearer",
      "expires_in": 3599
    }

Device flow

The device flow is designed for client devices that have limited user interfaces, such as a set-top box, streaming radio, or a server process running on a headless operating system.

Rather than logging in by using the client device itself, you can authorize the client to access protected resources on your behalf by logging in with a different user agent, such as an Internet browser or smartphone, and entering a code displayed on the client device.

OAuth 2.0 device flow
Figure 17. OAuth 2.0 device flow
Device flow explained
  1. The client device requests a device code from AM.

  2. AM returns a device code, a user code, a URL for entering the user code, and an interval, in seconds.

  3. The client device provides instructions to the user to enter the user code. The client may choose an appropriate method to convey the instructions, for example, text instructions on screen, or a QR code.

  4. The client device begins to continuously poll AM to see if authorization has been completed.

  5. If the user has not yet completed the authorization, AM returns an HTTP 403 status code, with an authorization_pending message.

  6. The user follows the instructions from the client device to enter the user code by using a separate device.

  7. If the user code is valid, AM redirects the resource owner for authentication.

  8. Upon authentication, the user is prompted to confirm the user code. The page is pre-populated with the one entered before.

  9. The user can authorize the client device. The AM consent page also displays the requested scopes, and their values.

    AM does not display the confirmation nor the consent pages if the user has a valid session when they entered the code, and the client is allowed to skip consent.

    This is also true if you perform the call using REST and pass the decision=allow parameter.

  10. Upon authorization, AM responds to the client device’s polling with an HTTP 200 status, and an access token, giving the client device access to the requested resources.

The following procedures show how to use the OAuth 2.0 device flow endpoints:

Get a user code for the device

Devices can display a user code and instructions for a user, which can be used on a separate client to provide consent, allowing the device to access resources.

User codes consist of a random selection of a configurable set of characters.

By default, the user code is generated using eight of the following characters:

234567ABCDEFGHIJKLMNOPQRSTVWXYZabcdefghijkmnopqrstvwxyz

You can configure the list of possible characters to improve usability. For example, remove similar characters such as 'l' and 'I' to reduce ambiguity on low resolution device screens, or limit input to either alphabetical or numerical characters to suit mobile keyboards.

The length of the user code is also configurable.

For more information, see the device flow configuration.

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server.

    Ensure that the Device Code grant type is configured in the Grant Types field.

    For more information, see Authorization server configuration.

  • A public client called myClient is registered in AM with the following configuration:

    • Scopes: write

    • Grant Types: Device Code

For more information, see Client registration.

Perform the following steps to request a user code in the OAuth 2.0 device flow:

  1. The client creates a POST request to the /oauth2/device/code endpoint specifying the client ID, myClient, as a minimum.

    For information about the parameters supported by the /oauth2/device/code endpoint, see /oauth2/device/code. For information about private client authentication methods, see OAuth 2.0 client authentication.

    For example:

    $ curl \
    --request POST \
    --data "client_id=myClient" \
    --data "scope=write" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/code"
    {
        "interval": 5,
        "device_code": "7a95a0a4-6f13-42e3-ac3e-d3d159c94c55…​",
        "verification_uri": "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user",
        "verification_url": "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user",
        "verification_uri_complete": "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user?user_code=VAL12e0v",
        "user_code": "VAL12e0v",
        "expires_in": 300
    }

    On success, AM returns a user code, a verification URI, and a verification_uri_complete value comprising the user code appended to the URI, which can be used to create QR codes.

    The verification_url output is included to support earlier versions of the specification.

    AM also returns an interval, in seconds, that the client device must wait for in between requests for an access token.

    Go to Realms > Realm Name > Services > OAuth2 Provider > Device Flow to configure the returned values.

  2. The client device should now provide instructions to the user to enter the user code and grant access to the OAuth 2.0 device.

    The client may choose an appropriate method to convey the instructions, for example, text instructions on screen, or a QR code. Perform the steps in one of the following procedures:

  3. The client device should also begin polling the authorization server for the access token using the interval and device code information obtained in the previous step.

    For more information, see Poll for authorization.

Grant consent with a user code without using a browser

The OAuth 2.0 device flow requires that the user grants consent to allow the client device to access the resources. The authorization server would then provide the client with an access token.

To grant consent with a user code without using a browser, perform the following steps:

  1. The resource owner logs in to the authorization server, for example, using the credentials of the demo user.

    For example:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  2. The client makes a POST call to the authorization server’s authorization device user endpoint specifying in a cookie SSO token of the demo and, at least, the following parameters:

    • user_code*=resource-owner-user-code

    • decision*=allow

    • csrf*=demo-user-SSO-token

    For information about the parameters supported by the /oauth2/device/user endpoint, see /oauth2/device/user.

    The tenant session cookie (<session-cookie-name>) is required and should contain the SSO token of the user granting access to the client. For example:

    $ curl \
    --request POST \
    --header "Cookie: <session-cookie-name>=AQIC5wM…​TU3OQ*" \
    --data "user_code=VAL12e0v" \
    --data "decision=allow" \
    --data "csrf=AQIC5wM…​TU3OQ*" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user"

    The scope and the client_id parameters have not been included because the user code already contains that information.

    AM returns HTML containing a JavaScript fragment named pageData, with details of the result.

    Successfully allowing or denying access returns:

    pageData = {
        locale: "en_US",
        baseUrl : "https://<tenant-name>.forgeblocks.com/am/XUI/",
        realm : "/alpha",
        done: true
    }

    done: true means that the flow can now continue.

    If the supplied user code has already been used, or is incorrect, AM returns the following:

    pageData = {
        locale: "en_US",
        errorCode: "not_found",
        realm : "/alpha",
        baseUrl : "https://<tenant-name>.forgeblocks.com/am/XUI/"
        oauth2Data: {
              csrf: "ErFIk8pMraJ1rvKbloTgpp6b7GZ57kyk9HaIiKMVK3g=",
              userCode: "VAL12e0v",
        }
    }

    As per Section 4.1.1 of the OAuth 2.0 authorization framework, it is required that the authorization server legitimately obtains an authorization decision from the resource owner.

    Any client using the endpoints to register consent is responsible for ensuring this requirement, AM cannot assert that consent was given in these cases.

Grant consent with a user code using a browser

The OAuth 2.0 device flow requires that the user grants consent to allow the client device to access the resources.

The authorization server would then provide the client with an access token.

To grant consent with a user code using a browser, perform the following steps:

  1. The resource owner navigates to the verification URL acquired with the user code, for example, https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user.

  2. The resource owner logs in to the authorization server using, for example, the demo user credentials.

  3. The resource owner enters their user code:

    Visit the verification URL to enter the user code.
    Figure 18. OAuth 2.0 User Code
  4. The resource owner authorizes the device flow client by allowing the requested scopes:

    AM lists the scopes requested by the client device, and their values.
    Figure 19. OAuth 2.0 Consent Page

    If the client is allowed to skip consent, the user will not see this screen.

  5. AM adds the OAuth 2.0 client to the user’s profile page in the Authorized Apps section and displays that the user is done with the flow:

    The user code part of the device flow is done.
    Figure 20. OAuth 2.0 Done Page

    The device now can request an access token from AM.

Poll for authorization

The client device must poll the authorization server for an access token, since it cannot know whether the resource owner has already given consent or not.

Perform the following steps to poll for an access token:

  1. On the client device, create a POST request to poll the /oauth2/access_token endpoint to request an access token specifying, at least, the following parameters:

    • client_id=your-client-id

    • grant_type=urn:ietf:params:oauth:grant-type:device_code

    • device_code=your-device-code

    For information about the parameters supported by the /oauth2/access_token endpoint, see /oauth2/access_token.

    The client device must wait for the number of seconds previously provided as the value of interval between polling AM for an access token. For example:

    $ curl \
    --request POST \
    --data "client_id=myClient" \
    --data "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
    --data "device_code=7a95a0a4-6f13-42e3-ac3e-d3d159c94c55…​" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"

    If the user has authorized the client device, an HTTP 200 status code is returned, with an access token that can be used to request resources:

    {
        "expires_in": 3599,
        "token_type": "Bearer",
        "access_token": "c1e9c8a4-6a6c-45b2-919c-335f2cec5a40"
    }

    If the user has not yet authorized the client device, an HTTP 403 status code is returned, with the following error message:

    {
        "error": "authorization_pending",
        "error_description": "The user has not yet completed authorization"
    }

    If the client device is polling faster than the specified interval, an HTTP 400 status code is returned, with the following error message:

    {
        "error": "slow_down",
        "error_description": "The polling interval has not elapsed since the last request"
    }

    The authorization server can also issue refresh tokens at the same time the access tokens are issued. For more information, see Refresh tokens.

Device flow with PKCE

The device flow is designed for client devices that have limited user interfaces, such as a set-top box. Since the devices are usually public clients and the device code can be intercepted by malicious users, you can combine the device flow with the PKCE standard (RFC 7636) to mitigate against interception attacks if the devices allow it.

AM implements this flow by adding the following parameters on top of those used for the device flow grant:

  • code_verifier (form parameter). Contains a random string that correlates the authorization request to the token request.

  • code_challenge (query parameter). Contains a string derived from the code verifier that is sent in the authorization request and that needs to be verified later with the code verifier.

  • code_challenge_method (query parameter). Contains the method used to derive the code challenge.

OAuth 2.0 Device Flow with PKCE
Figure 21. OAuth 2.0 Device Flow with PKCE
Device flow with PKCE explained
  1. When using the PKCE standard, the device must be able to generate a code verifier and a code challenge. For details, see the PKCE standard (RFC 7636).

    For a JavaScript example that generates a code verifier and a code challenge, see here.

  2. The client device requests a device code from AM, appending the code challenge previously generated to the request.

  3. AM returns a device code, a user code, a URL for entering the user code, and an interval, in seconds.

  4. The client device provides instructions to the user to enter the user code. The client may choose an appropriate method to convey the instructions, for example, text instructions on screen, or a QR code.

  5. The client device begins to continuously poll AM to see if authorization has been completed, appending the code verifier previously generated.

  6. If the user has not yet completed the authorization, AM returns an HTTP 403 status code, with an authorization_pending message.

  7. The user follows the instructions from the client device to enter the user code by using a separate device.

  8. The authorization server verifies the code challenge stored in memory using the validation code. It also verifies the user code. If both codes are valid, AM redirects the resource owner for authentication.

  9. Upon authentication, the user is prompted to confirm the user code. The page is pre-populated with the one entered before.

  10. The user can authorize the client device. The AM consent page also displays the requested scopes, and their values.

    AM does not display the confirmation nor the consent pages if the user has a valid session when they entered the code, and the client is allowed to skip consent.

    This is also true if you perform the call using REST and pass the decision=allow parameter.

  11. Upon authorization, AM responds to the client device’s polling with an HTTP 200 status, and an access token, giving the client device access to the requested resources.

The following procedures show how to use the OAuth 2.0 device flow endpoints:

Get a user code for the device

Devices can display a user code and instructions for a user, which can be used on a separate client to provide consent, allowing the device to access the resources.

Devices can display a user code and instructions for a user, which can be used on a separate client to provide consent, allowing the device to access resources.

User codes consist of a random selection of a configurable set of characters.

By default, the user code is generated using eight of the following characters:

234567ABCDEFGHIJKLMNOPQRSTVWXYZabcdefghijkmnopqrstvwxyz

You can configure the list of possible characters to improve usability. For example, remove similar characters such as 'l' and 'I' to reduce ambiguity on low resolution device screens, or limit input to either alphabetical or numerical characters to suit mobile keyboards.

The length of the user code is also configurable.

For more information, see the device flow configuration.

This procedure assumes the following configuration:

  • AM is configured as an OAuth 2.0 authorization server. Ensure that:

    • The Device Code grant type is configured in the Grant Types field.

    The Code Verifier Parameter Required setting (Realms > Realm Name > Services > OAuth2 Provider > Advanced) specifies whether AM requires clients to include a code verifier in their calls. However, if a client makes a call to AM with the code_challenge parameter, AM will honor the code exchange regardless of the Code Verifier Parameter Required value. For more information, see Authorization server configuration.

  • A public client called myClient is registered in AM with the following configuration:

    • Scopes: write

    • Grant Types: Device Code

For more information, see Client registration.

Perform the following steps to request a user code in the OAuth 2.0 device flow:

  1. The client creates a POST request to the /oauth2/device/code endpoint specifying, at least, the following parameters:

    • client_id=your-client-id

    • code_challenge=your-code-challenge

    • code_challenge_method=S256

      Creating the challenge using a SHA-256 algorithm is mandatory if the device supports it, as per the RFC 7636 standard.

    For information about the parameters supported by the /oauth2/device/code endpoint, see /oauth2/device/code. For information about private client authentication methods, see OAuth 2.0 client authentication.

    For example:

    $ curl \
    --request POST \
    --data "client_id=myClient" \
    --data "code_challenge=j3wKnK2Fa_mc2tgdqa6GtUfCYjdWSA5S23JKTTtPF8Y" \
    --data "code_challenge_method=S256" \
    --data "scope=write" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/code"
    {
        "interval": 5,
        "device_code": "7a95a0a4-6f13-42e3-ac3e-d3d159c94c55…​",
        "verification_uri": "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user",
        "verification_url": "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user",
        "verification_uri_complete": "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user?user_code=VAL12e0v",
        "user_code": "VAL12e0v",
        "expires_in": 300
    }

    On success, AM returns a user code, a verification URI, and a verification_uri_complete value comprising the user code appended to the URI, which can be used to create QR codes.

    The verification_url output is included to support earlier versions of the specification.

    AM also returns an interval, in seconds, that the client device must wait for in between requests for an access token.

    Go to Realms > Realm Name > Services > OAuth2 Provider > Device Flow to configure the returned values.

  2. The client device should now provide instructions to the user to enter the user code and grant access to the OAuth 2.0 device.

    The client may choose an appropriate method to convey the instructions, for example, text instructions on screen, or a QR code. Perform the steps in one of the following procedures:

  3. The client device should also begin polling the authorization server for the access token using the interval and device code information obtained in the previous step and the PKCE code verifier.

For more information, see Poll for authorization.

Grant consent with a user code without using a browser

The OAuth 2.0 device flow requires that the user grants consent to allow the client device to access the resources. The authorization server would then provide the client with an access token.

To grant consent with a user code without using a browser, perform the following steps:

  1. The resource owner logs in to the authorization server, for example, using the credentials of the demo user.

    For example:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  2. The client makes a POST call to the authorization server’s authorization device user endpoint specifying in a cookie SSO token of the demo and, at least, the following parameters:

    • user_code*=resource-owner-user-code

    • decision*=allow

    • csrf*=demo-user-SSO-token

    For information about the parameters supported by the /oauth2/device/user endpoint, see /oauth2/device/user.

    The tenant session cookie (<session-cookie-name>) is required and should contain the SSO token of the user granting access to the client. For example:

    $ curl \
    --request POST \
    --header "Cookie: <session-cookie-name>=AQIC5wM…​TU3OQ*" \
    --data "user_code=VAL12e0v" \
    --data "decision=allow" \
    --data "csrf=AQIC5wM…​TU3OQ*" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user"

    The scope and the client_id parameters have not been included because the user code already contains that information.

    AM returns HTML containing a JavaScript fragment named pageData, with details of the result.

    Successfully allowing or denying access returns:

    pageData = {
        locale: "en_US",
        baseUrl : "https://<tenant-name>.forgeblocks.com/am/XUI/",
        realm : "/alpha",
        done: true
    }

    done: true means that the flow can now continue.

    If the supplied user code has already been used, or is incorrect, AM returns the following:

    pageData = {
        locale: "en_US",
        errorCode: "not_found",
        realm : "/alpha",
        baseUrl : "https://<tenant-name>.forgeblocks.com/am/XUI/"
        oauth2Data: {
              csrf: "ErFIk8pMraJ1rvKbloTgpp6b7GZ57kyk9HaIiKMVK3g=",
              userCode: "VAL12e0v",
        }
    }

    As per Section 4.1.1 of the OAuth 2.0 authorization framework, it is required that the authorization server legitimately obtains an authorization decision from the resource owner.

    Any client using the endpoints to register consent is responsible for ensuring this requirement, AM cannot assert that consent was given in these cases.

Grant consent with a user code using a browser

The OAuth 2.0 device flow requires that the user grants consent to allow the client device to access the resources.

The authorization server would then provide the client with an access token.

To grant consent with a user code using a browser, perform the following steps:

  1. The resource owner navigates to the verification URL acquired with the user code, for example, https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user.

  2. The resource owner logs in to the authorization server using, for example, the demo user credentials.

  3. The resource owner enters their user code:

    Visit the verification URL to enter the user code.
    Figure 22. OAuth 2.0 User Code
  4. The resource owner authorizes the device flow client by allowing the requested scopes:

    AM lists the scopes requested by the client device, and their values.
    Figure 23. OAuth 2.0 Consent Page

    If the client is allowed to skip consent, the user will not see this screen.

  5. AM adds the OAuth 2.0 client to the user’s profile page in the Authorized Apps section and displays that the user is done with the flow:

    The user code part of the device flow is done.
    Figure 24. OAuth 2.0 Done Page

    The device now can request an access token from AM.

Poll for authorization

The client device must poll the authorization server for an access token, since it cannot know whether the resource owner has already given consent or not.

Perform the following steps to poll for an access token:

  1. On the client device, create a POST request to poll the /oauth2/access_token endpoint to request an access token specifying, at least, the following parameters:

    • client_id*=your-client-id

    • *grant_type=urn:ietf:params:oauth:grant-type:device_code

    • device_code=your-device-code

    • code_verifier=your-code-verifier

    For information about the parameters supported by the /oauth2/access_token endpoint, see /oauth2/access_token.

    The client device must wait for the number of seconds previously provided as the value of interval between polling AM for an access token. For example:

    $ curl \
    --request POST \
    --data "client_id=myClient" \
    --data "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
    --data "device_code=7a95a0a4-6f13-42e3-ac3e-d3d159c94c55…​" \
    --data "code_verifier=ZpJiIM_G0SE9WlxzS69Cq0mQh8uyFaeEbILlW8tHs62SmEE6n7Nke0XJGx_F4OduTI4" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"

    If the user has authorized the client device, an HTTP 200 status code is returned, with an access token that can be used to request resources:

    {
        "expires_in": 3599,
        "token_type": "Bearer",
        "access_token": "c1e9c8a4-6a6c-45b2-919c-335f2cec5a40"
    }

    If the user has not yet authorized the client device, an HTTP 403 status code is returned, with the following error message:

    {
        "error": "authorization_pending",
        "error_description": "The user has not yet completed authorization"
    }

    If the client device is polling faster than the specified interval, an HTTP 400 status code is returned, with the following error message:

    {
        "error": "slow_down",
        "error_description": "The polling interval has not elapsed since the last request"
    }

    The authorization server can also issue refresh tokens at the same time the access tokens are issued. For more information, see Refresh tokens.

SAML v2.0 profile for authorization grant

The SAML v2.0 profile for authorization grant is designed for environments that want to leverage the REST-based services provided by AM’s OAuth 2.0 support, while keeping their existing SAML v2.0 federation implementation.

The RFC 7522 describes the means to use SAML v2.0 bearer assertions to request access tokens and to authenticate OAuth 2.0 clients.

At present, AM implements the profile to request access tokens.

Consider the following requirements before implementing this flow:

  • The client (the application the resource owner uses to start the flow) must inform the resource owner that, by authenticating to the SAML v2.0 identity provider, the resource owner grants the client access to the protected resources. AM does not present the resource owner with consent pages.

    This client must be able to consume the access token and handle errors as required.

  • The OAuth 2.0 authorization service and SAML v2.0 service provider must be configured in the same AM instance.

  • The service provider must require that assertions are signed.

  • The SAML v2.0 identity provider must issue signed assertions.

    The assertion must contain the SAML v2.0 entity names, as follows:

    • The issuer must be set to the identity provider’s name. For example, https://idp.example.com:8443/idp.

    • The audience must be set to the service provider’s name. For example, https://<tenant-name>.forgeblocks.com/am.

  • The identity provider and the service provider must belong to the same circle of trust.

  • AM must be able to determine the resource owner from the name ID contained in the assertion. Failure to determine the resource owner results in an error similar to:

    {"error_description":"AM identity should not be null","error":"server_error"}

    AM may fail to determine the resource owner if the assertion contains an opaque name ID during transient federation. Because the opaque reference is never stored during a transient flow, the OAuth 2.0 provider cannot determine the resource owner it relates to.

    To work around this, configure an identity in the Transient User field of the SAML v2.0 service provider. This will map all transient ID references to that identity.

  • The OAuth 2.0 client is registered, at least, with the following configuration:

    • Grant Types: SAML2

  • The OAuth 2.0 provider is configured. Ensure that:

    • The SAML2 grant type is configured in the Grant Types field.

The following diagram demonstrates the SAML v2.0 profile for authorization grants:

SAML v2.0 Profile for Authorization Grant Flow
Figure 25. SAML v2.0 Profile for Authorization Grant Flow
  1. The client requests the SAML v2.0 identity provider the SAML v2.0 assertion related to the resource owner. Usually, this means the client redirects the resource owner to the identity provider for authentication.

  2. The SAML v2.0 identity provider returns the signed assertion to the client.

  3. The client includes the assertion and a special grant type in the call to the OAuth 2.0 token endpoint in the following parameters:

    • grant_type=urn:ietf:params:oauth:grant-type:saml2-bearer

    • assertion=my-assertion

      Note that the assertion must be first base64-encoded, and then URL encoded.

    For example:

    $ curl \
    --request POST \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data-urlencode "assertion=PHNhbWxwOl…​ZT4" \
    --data "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2-bearer" \
    --data "redirect_uri=https://www.example.com:443/callback" \
    --data "scope=write" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"
  4. The AM authorization server validates the assertion. If the assertion is valid, the authorization server returns an access token to the client.

  5. The client request access to the protected resources from the resource server.

  6. The resource server contacts the authorization server to validate the access token.

  7. The authorization server validates the token and responds to the resource server.

  8. If the token is valid, the resource server allows the client to access the protected resources.

JWT profile for OAuth 2.0 authorization grant

The JWT profile for OAuth 2.0 authorization grant is designed for environments that want to leverage the REST-based services provided by AM’s OAuth 2.0 framework while keeping their existing authentication services, as long as the trust relationship can be expressed with a JWT bearer token.

Since the trust relationship is already established, this flow does not require the end user’s interaction.

The RFC 7523 defines the use of JWT bearer tokens for both requesting access tokens as well as for client authentication.

Read this section for information about requesting access tokens. To use JWTs for client authentication, see Authenticate clients with JWT profiles.

As the authorization server, AM must validate the bearer JWT to issue the access token to the client. To ensure that malicious clients cannot self-sign their own JWTs to acquire tokens, AM requires the token issuer to be pre-registered in AM as an special type of agent.

JWT Bearer Profile for Authorization Grant
Figure 26. JWT Bearer Profile for Authorization Grant
  1. The client requests a JWT from the issuer. The client itself can be the issuer, in which case it will create a JWT for itself before starting the OAuth 2.0 flow.

    Regardless of who signs the JWT, the issuer must be pre-registered in AM as a trusted JWT issuer. For more information, see Configure a trusted JWT issuer agent.

  2. The issuer returns a signed JWT to the client; JWTs with message authentication codes (MACs) applied to them are not supported.

    The JWT must contain, at least, the following claims in the payload:

    • aud. Specifies a string or an array of strings that is the intended audience of the JWT. Must be set to, or contain, the authorization server’s token endpoint.

    • exp. Specifies the expiration time of the JWT in Unix time.

      Providing a JWT with an expiry time greater than 30 minutes causes AM to return a JWT expiration time is unreasonable error message.

    • iss. Specifies the unique identifier of the JWT issuer. This could be the client or a third party.

      The identifier must match the issuer field configured in the trusted JWT issuer agent.

    • sub. Specifies the principal who is the subject of the JWT. It must be a string that identifies the resource owner.

      You can configure the trusted JWT issuer agent to check a different claim for the principal. For example, the preferred_username from an ID token.

      In this case, the JWT would contain both the sub and the preferred_username claims.

      For more information, see Configure a trusted JWT issuer agent.

      The following is an example of the payload of a basic JWT:

      {
        "aud": [
          "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/access_token"
        ],
        "iss": "https://www.example.com/issuer",
        "exp": 1555530663,
        "sub": "demo"
      }

      For an example of a JWT containing different claims as supported by the trusted JWT issuer agent, see Configure a trusted JWT issuer agent.

      For more information about JWTs, see the RFC 7523 standard.

  3. The client includes the JWT and a client assertion type in the call to the OAuth 2.0 endpoint in the following parameters:

    • grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer

    • assertion=my-JWT

    For example:

    $ curl \
    --request POST \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer" \
    --data "assertion=eyAiYWxnIjogIlJTMjU2IiB9.eyAic3ViIjogImp3…​"
    --data "redirect_uri=http://www.example.com" \
    --data "scope=write" \
    "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"

    For information about the parameters supported by the /oauth2/access_token endpoint, see /oauth2/access_token.

    For more information about client authentication methods, see OAuth 2.0 client authentication.

  4. AM validates the JWT following the guidance specified in section 3 of the RFC7523 and also performs the following additional checks:

    1. Decodes the payload and compares the value of the iss claim with the value of the JWT Issuer field in the list of trusted JWT issuer agents.

    2. Validates the JWT signature either with the keys exposed on the trusted issue agent’s JWK URI, or with the keys configured in the JWK Set field of the agent.

    If AM cannot validate the JWT it will return an error, such as JWT signature is invalid.

  5. The authorization server issues an access token to the client.

  6. The client requests access to the protected resources from the resource server.

  7. The resource server contacts the authorization server to validate the access token.

  8. The authorization server validates the token and responds to the resource server.

  9. If the token is valid, the resource server allows the client to access the protected resources.

Configure a trusted JWT issuer agent

Perform the steps in this procedure to configure a trusted JWT issuer agent:

  1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Trusted JWT Issuer.

  2. Add a new trusted JWT issuer agent.

  3. Complete the following fields to create the agent:

    • In the Agent ID field, give the trusted JWT issuer agent a name.

      For example, myJWTAgent.

    • In the JWT Issuer field, provide the URI of the JWT issuer.

      This URI must match the value of the issuer (the iss claim) in the JWTs.

    • Select Create.

      You are presented with a screen with additional information regarding the agent.

  4. Review the trusted JWT issuer agent information.

    You must, configure either the JWKs URI or the JWK Set fields, as follows:

    • JWKs URI: specifies a URI in the JWT issuer that exposes the verification keys that AM will use to validate the JWT signature. For example, http://www.example.com/issuer/jwk_uri.

      If you configure this field, ensure the following properties are configured with sensible values for your environment:

      • JWKs URI content cache timeout in ms

      • JWKs URI content cache miss cache time

    • JWK set: Specifies a JWK set containing the verification keys to validate the JWT signature.

      The following is an example of an elliptic curve JWK set:

      {
        "keys": [{
           "kty": "EC",
           "crv": "P-256",
           "x": "i-rdOmi5lC3pn3y5sTgYiLLFVFY7XxDLinWneHEaAXA",
           "y": "mxmqqauiq44INgyyPP2vATt3IkDL_6W5CAcfAMSZl8k",
           "kid": "signing_key",
           "x5c": [
               "MIIBSjCB76ADAgEC.....955PByPrflZkQOC/g==" ]
        }]
      }

      For more information about the contents of the JWK set, see the JSON Web Key (JWK) specification.

    You can store more than one key in the JWK set. However, it is easier to implement key rotation exposing the validation keys on the URI instead.

  5. Configure the following values to suit your environment:

    • Consented Scopes Claim. The name of a JWT claim that indicates which scopes the resource owner consented to. The claim in the JWT can contain either a JSON array or a space-separated allowlist of scopes that the resource owner has consented to.

      For example, if you configure the scp claim name in this field and the JWT contains the claim "scp":"read", but you request both the read and write scopes, AM will only grant the read scope.

      Leave this field blank to allow any scope.

      The following are example JWTs containing a claim that specifies scopes:

      {
         "aud": [
             "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/access_token"
         ],
         "iss": "https://www.example.com/issuer",
         "exp": 1555530663,
         "sub": "demo",
         "scope": ["read", "write"]
      }

      In this case, the scope claim is a JSON array of scopes.

      {
         "aud": [
             "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/access_token"
         ],
         "iss": "https://www.example.com/issuer",
         "exp": 1555530663,
         "sub": "demo",
         "scp": "read write"
      }

      In this case, the scp claim is a space-separated list of scopes.

    • Resource Owner Identity Claim. Claim in the JWT that identifies the resource owner in AM. By default, the sub claim.

      Note that even if you configure the trusted JWT issuer agent to verify a different claim, such as the preferred_username claim, the sub claim must still exist in the JWT.

    • Allowed Subjects. List of subjects this JWT issuer is allowed to provide consent for.

      For example, if you configure the demo user in this field but the JWT subject value is demo2, AM will not grant the access token.

      Leave it blank to provide consent to any user.

  6. Save your changes.

    The trusted JWT issuer agent is ready for use.

OAuth 2.0 endpoints

When acting as an OAuth 2.0 authorization server, AM exposes the following endpoints:

Table 4. OAuth 2.0 Endpoints
Endpoint Description

Register a pushed authorization request and get a request URI (RFC 9126 PAR endpoint)

Obtain consent and an authorization grant (RFC 6749 authorization endpoint)

Initiate backchannel authorization (Backchannel flow endpoint)

Obtain an access token (RFC 6749 token endpoint)

Obtain a device code (Device flow endpoint)

Obtain consent and authorization grant (Device flow endpoint)

Revoke both access and refresh tokens (RFC 7009 endpoint)

Retrieve metadata about a token, such as approved scopes and the context in which the token was issued (RFC 7662 endpoint)

Retrieve metadata about a macaroon, and add caveats.

As an OAuth 2.0/OpenID Connect provider, AM also exposes the following:

/oauth2/par

The /oauth2/par endpoint is the OAuth 2.0 pushed authorization request (PAR) endpoint as defined in RFC 9126.

Use this endpoint to push an authorization request payload directly to the authorization server. The endpoint can be used in conjunction with the following grant flows:

You must compose the path to the PAR endpoint using the specific realm for the OAuth 2.0 provider. For example, if the provider is configured for the alpha subrealm, then use:

https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/par.

The PAR endpoint supports the following parameters:

client_id

Specifies the client ID unique to the application making the request.

Required: Yes, even when it is also included in a request object.

client_secret

Specifies the password of the private client making the request. Do not use in conjunction with the cnf_key parameter.

Required: Confidential clients require some type of credential. However, the use of the client_secret parameter depends on the client authentication method used. For more information, see OAuth 2.0 client authentication.

request

A signed and optionally encrypted JWT object containing the request parameters.

The JWT must include the following claims:

  • client_id

    This must be included even though it is also a required parameter of the request itself.

  • response_type

    See response_type for details of this required parameter.

  • exp and nbf

    Include the exp and nbf claims if they are set as mandatory in the OAuth 2.0 provider configuration.

    The exp (expiration time) and nbf (not before) claims provide the timeframe within which the JWT is valid. If specified, these values are used to validate the JWT, even when they are not required.

    To ensure the values meet the requirements for the Financial-grade API (FAPI) security profile, see the OAuth2 provider configuration.

  • All other parameters that are required for the successful completion of the grant flow must be included, too. For example, you need to define code_challenge for an Authorization code grant with PKCE flow.

    If a JWT request object is specified, no other parameters are permitted in the request itself except for client authentication parameters.

    All other request details must be defined as claims in the JWT, otherwise the request returns an Invalid parameter scope error.

The following is an example of a request object.

{
  "client_id": "myClient",
  "nbf": 1594140030,
  "redirect_uri": "https://www.example.com:8443",
  "scope" : "write",
  "exp": 1594140390,
  "response_type" : "code",
  "code_challenge" :  "QR1D-7w1-rOQvlFe1CeqZigqaIpmZXatDMVvZ50o",
  "code_challenge_method" : "S256"
}

Required: No.

response_type

Specifies the type of response expected from the authorization server. Set this parameter to one of the following values:

  • code, to request an authorization code during the authorization code grant flow.

  • token, to request an access token during the implicit grant flow.

  • id_token, to request an ID token during the implicit grant flow

  • code token, to request an authorization code and an access token during the hybrid grant flow.

  • code id_token, to request an authorization code and an ID token during the hybrid grant flow.

  • code token id_token, to request an authorization code, an access token, and an ID token during the hybrid grant flow.

  • token id_token, to request an access token and an ID token during the implicit grant flow.

  • none, to request AM not to issue any token or code in the request. Use this response type in conjunction with the id_token_hint parameter only.

Required: Yes, but as a JWT claim if a request object is specified.

csrf

When interacting with the OAuth 2.0 consent page, this parameter helps prevent against cross-site request forgery (CSRF) attacks.

The parameter duplicates the contents of the iPlanetDirectoryPro cookie, which contains the SSO token of the resource owner giving consent.

When using the AM consent pages, this parameter is set in the consent page once the resource owner has authenticated, and it is sent to AM along with the consent.

When replacing AM consent pages with your own consent pages or when trying the flows without a browser, you must set this parameter manually. For an example of a curl command, see the Authorization code grant.

Required: Yes, for calls that are submitting consent response, unless you use the Remote Consent Service to gather consent.

code_challenge

Specifies a string derived from the code verifier that is sent in the authorization request during the authorization code with PKCE grant flow.

Required: Yes, required for clients that are registered as confidential, or when requesting an authorization code during the Authorization code grant with PKCE flow, regardless of client registration type.

code_challenge_method

Contains the method used to derive the code challenge. Possible values are plain and S256. When unset, it defaults to plain. For clients that are registered as confidential, this value must be set to S256.

Required: Yes, when requesting an authorization code during the Authorization code grant with PKCE flow and the code challenge was created using an SHA256 algorithm.

decision

Specifies whether the resource owner consents to the requested access. Set to allow to grant consent. Any other value denies consent.

Required: Yes, for calls that are submitting consent response, unless consent is already saved for the scope.

redirect_uri

The URI to return the resource owner to after authorization is complete. If not set, the redirection URI defaults to that configured in the client profile registered with AM.

Required: No.

response_mode

Set to form_post to return a self-submitting form that contains the code instead of redirecting to the redirect URL with the code as a string parameter. For more information, see the OAuth 2.0 Form Post Response Mode spec.

Required: No.

scope

Specify the scopes linked to the permissions requested by the client from the resource owner. If not specified, the default scopes specified in the client or the authorization server are requested.

Required: No.

save_consent

Updates the resource owner’s profile to avoid having to prompt the resource owner to grant authorization when the client issues subsequent authorization requests.

Set this parameter to on to save the consent.

To save the consent, you must have configured the Saved Consent Attribute Name property with a profile attribute in which to store the resource owner’s consent decision.

For more information on setting this property in the OAuth2 provider service, see OAuth2 Provider.

Required: No.

service/module

Use either as described in Authentication Parameters, where module specifies the authentication module instance to use, or service specifies the authentication tree or chain to use when authenticating the resource owner.

If not specified, the resource owner authenticates using the default chain or tree configured for the realm.

Required: No.

state

Value to maintain state between the request and the callback. During authentication, the client sends this parameter to the authorization server. The authorization server must send it back unchanged in the response.

The application should use this value to ensure the response belongs to the user that initiated the requests, which mitigates CSRF attacks.

The value of state is typically a base64-encoded string that contains user state and that is unique to a user and their request.

Required: No, but it is strongly recommended.

acr_values

Authentication context class reference values used to communicate acceptable LoAs that users must satisfy when authenticating to the OpenID provider.

Required: No. OIDC flows only.

claims

Specifies a JSON object containing specific attributes about users to be returned in the ID Token.

Required: No. OIDC flows only.

id_token_hint

ID token previously issued by AM that is passed as a hint about the end user’s session with the client. Using this parameter requires the response_type and prompt parameters to be set to none.

For more information about using the id_token_hint parameter, see Session Management Draft 10.

Required: No. OIDC flows only.

login_hint

String value that can be set to the ID the user uses to log in. For example, Bob or bob@example.com, depending on how the authentication node is configured to search for users.

When provided as part of the OIDC authentication request, the login_hint is set as the value of a cookie named oidcLoginHint, which is an HttpOnly cookie (only sent over HTTPS).

For more information, see GSMA Mobile Connect.

Required: No. OIDC flows only.

nonce

String value that associates the client session with the ID token that also mitigates against replay attacks. For more information, see OpenID Connect 1.0.

Required: No. OIDC flows only.

prompt

A space-separated, case-sensitive list of ASCII values that specifies whether AM should prompt the end user for authentication and consent. Possible values are:

  • none. AM does not display authentication or consent pages. Use with the id_token_hint and the response_type=none parameters only.

  • login. AM prompts the end user to authenticate to the default service of their realm, or to the service provided in the service parameter.

    If the user reauthenticates to a tree, AM destroys the original session and provides them with a new one that reflects the new authentication journey.

    If the user reauthenticates to a chain, AM updates the original session to reflect the new authentication journey.

  • consent. AM prompts the end user to grant consent, even if a consent response was previously saved.

Required: No. OIDC flows only.

ui_locales

Specifies a space-separated list of the end user preferred languages for the user interface, ordered by preference. For example, en fr-CA fr.

Required: No. OIDC flows only.

request_uri

PAR permits any of the parameters applicable to the /authorize endpoint, except for request_uri. It is invalid to specify this parameter in a PAR request.

Required: No.

/oauth2/authorize

The /oauth2/authorize endpoint is the OAuth 2.0 authorization endpoint as defined in RFC 6749. Use this endpoint to gather consent and authorization from the resource owner when using the following flows:

You must compose the path to the authorize endpoint addressing the specific realm where the access code will be issued. For example, https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/authorize.

The authorization endpoint supports the following parameters:

client_id

Specifies the client ID unique to the application making the request.

For PAR flows, or to adhere to the JAR specification, this value must match the client_id claim in the request object.

Required: Yes.

response_type

Specifies the type of response expected from the authorization server. Set this parameter to one of the following values:

  • code, to request an authorization code during the Authorization Code grant flow.

  • token, to request an access token during the Implicit grant flow.

  • id_token, to request an ID token during the Implicit grant flow

  • code token, to request an authorization code and an access token during the Hybrid grant flow.

  • code id_token, to request an authorization code and an ID token during the Hybrid grant flow.

  • code token id_token, to request an authorization code, an access token, and an ID token during the Hybrid grant flow.

  • token id_token, to request an access token and an ID token during the Implicit grant flow.

  • none, to request AM not to issue any token or code in the request. Use this response type in conjunction with the id_token_hint parameter only.

Required: Yes.

csrf

When interacting with the OAuth 2.0 consent page, this parameter helps prevent against Cross-Site Request Forgery (CSRF) attacks.

The parameter duplicates the contents of the tenant session cookie, which contains the SSO token of the resource owner giving consent.

When using the AM consent pages, this parameter is set in the consent page once the resource owner has authenticated, and it is sent to AM along with the consent.

When replacing AM consent pages with your own consent pages or when trying the flows without a browser, you must set this parameter manually. For an example of a curl command, see the Authorization code grant.

Required: Yes, unless you use the Remote Consent Service to gather consent.

code_challenge

Specifies a string derived from the code verifier that is sent in the authorization request during the Authorization Code with PKCE grant flow.

Required: Yes, when requesting an authorization code during the Authorization code grant with PKCE flow.

code_challenge_method

Contains the method used to derive the code challenge. Possible values are plain and S256. When unset, it defaults to plain.

Required: Yes, when requesting an authorization code during the Authorization code grant with PKCE flow and the code challenge was created using an SHA256 algorithm.

decision

Specifies whether the resource owner consents to the requested access. Set to allow to grant consent. Any other value denies consent.

Required: Yes, unless consent is already saved for the scope.

redirect_uri

The URI to return the resource owner to after authorization is complete. If not set, the redirection URI defaults to that configured in the client profile registered with AM.

Required: No.

response_mode

Set to form_post to return a self-submitting form that contains the code instead of redirecting to the redirect URL with the code as a string parameter. For more information, see the OAuth 2.0 Form Post Response Mode spec.

Required: No.

scope

Specify the scopes linked to the permissions requested by the client from the resource owner. If not specified, the default scopes specified in the client or the authorization server are requested.

Required: No.

save_consent

Updates the resource owner’s profile to avoid having to prompt the resource owner to grant authorization when the client issues subsequent authorization requests.

Set this parameter to on to save the consent.

To save the consent, you must have configured the Saved Consent Attribute Name property with a profile attribute in which to store the resource owner’s consent decision.

For more information on setting this property in the OAuth2 Provider service, see OAuth2 Provider.

Required: No.

state

Value to maintain state between the request and the callback. During authentication, the client sends this parameter to the authorization server. The authorization server must send it back unchanged in the response.

The application should use this value to ensure the response belongs to the user that initiated the requests, which mitigates CSRF attacks.

The value of state is typically a base64-encoded string that contains user state and that is unique to a user and their request.

Required: No, but it is strongly recommended.

acr_values

Authentication Context class Reference values used to communicate acceptable LoAs that users must satisfy when authenticating to the OpenID provider.

Required: No. OIDC flows only.

claims

Specifies a JSON object containing specific attributes about users to be returned in the ID Token.

Required: No. OIDC flows only.

id_token_hint

ID token previously issued by AM that is passed as a hint about the end user’s session with the client. Using this parameter requires the response_type and prompt parameters to be set to none.

For more information about using the id_token_hint parameter, see Session Management Draft 10.

Required: No. OIDC flows only.

login_hint

String value that can be set to the ID the user uses to log in. For example, Bob or bob@example.com, depending on how the authentication node is configured to search for users.

When provided as part of the OIDC Authentication Request, the login_hint is set as the value of a cookie named oidcLoginHint, which is an HttpOnly cookie (only sent over HTTPS).

For more information, see GSMA Mobile Connect.

Required: No. OIDC flows only.

nonce

String value that associates the client session with the ID token that also mitigates against replay attacks. For more information, see OpenID Connect 1.0.

Required: No. OIDC flows only.

prompt

A space-separated, case-sensitive list of ASCII values that specifies whether AM should prompt the end user for authentication and consent. Possible values are:

  • none. AM does not display authentication or consent pages. Use with the id_token_hint and the response_type=none parameters only.

  • login. AM prompts the end user to authenticate to the default service of their realm, or to the service provided in the service parameter.

    If the user reauthenticates to a tree, AM destroys the original session and provides them with a new one that reflects the new authentication journey.

  • consent. AM prompts the end user to grant consent, even if a consent response was previously saved.

Required: No. OIDC flows only.

ui_locales

Specifies a space-separated list of the end user preferred languages for the user interface, ordered by preference. For example, en fr-CA fr.

Required: No. OIDC flows only.

request

Specifies a base64url-encoded JSON Web Token (JWT) whose claims are the parameters required for OpenID Connect flows or to comply with the JAR specification. This JWT is called the request object.

The validation rules applied to the request object depend upon the specification that is used to process the request.

OIDC requests that specify a request object are validated according to the specification set in the OAuth 2.0 provider configuration, OIDC or JAR. For details, see the Request Object Processing Specification configuration property.
JAR specification rules

The following rules apply if the OAuth 2.0 authorization JWT request does not contain OIDC-specific parameters, or if an Open ID Connect JWT request is configured for JAR processing:

  • The request object must be signed, and optionally, encrypted.

  • The client_id parameter must be defined in the request object. The value must match the [client_id] specified as a query parameter in the request itself.

  • Only the request object parameters are used for the authorization request, even when the same parameters are defined as query parameters.

OIDC specification rules

The following rules apply for OIDC JWT requests with default request object processing configuration (OIDC):

  • The request object does not need to be signed or encrypted.

  • You may send query string parameters and a request object in the same request to AM. This is useful to keep sensitive information protected in the request object, and to ensure that parameters whose value changes frequently, such as nonce and state, remain visible and mutable across calls.

    The value of the claims included in the request object supersede the value passed as query string parameters,

  • You must include the value of response_type and client_id as query string parameters, regardless of whether they are included in the request object or not.

    If they are included in the request object, their values must match those passed as query string parameters.

  • Include the openid scope as a query string parameter, regardless of whether it is included in the request object or not.

    The value of the scope claim may differ from that passed as a query parameter. This is useful to protect application-related scopes inside the request object, yet allows AM to process the request as part of an OpenID Connect flow.

Regardless of which specification is adhered to, you must include the exp and nbf claims if they are set as mandatory in the OAuth 2.0 provider configuration.

The exp (expiration time) and nbf (not before) claims provide the timeframe within which the JWT is valid. If specified, these values are used to validate the JWT, even when they are not required.

To ensure the values meet the requirements for the Financial-grade API (FAPI) security profile, see the OAuth2 provider configuration.

If the JWT is signed and/or encrypted, you must include the iss and aud parameters in the JWT, as shown in the Example request object.

These rules also apply if you’re passing the request object as a reference using the request_uri parameter.

Example request object

The following is an example of a request object.

Note that it includes both iss and aud, as well as the nbf and exp JWT claims, in addition to the OpenID Connect claims. However, AM ignores keys specified in JWT headers, such as `jku` and `jwe`.

{
  "iss": "myClient",
  "nbf": 1594140030,
  "client_id": "myClient",
  "aud": "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha",
  "redirect_uri": "https://www.example.com:8443",
  "exp": 1594140390,
  "scope" : ["openid", "profile"],
  "claims":
    {
      "id_token":
        {
          "acr":
            {
               "essential": true,
               "values": ["example_tree1","example_tree2"]
            }
        }
    }
}

If you are compressing the JWT, note that by default, AM rejects JWTs that expand to a size larger than 32 KiB (32768 bytes).

To retrieve a list of public keys clients can use to encrypt this JWT, make a request to the realm’s /oauth2/connect/jwk_uri.

The following is an example call sending the request object as value:

https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/authorize? \
&request=eyJhbGciOiJSUzI1NiIsImtpZCI6ImsyYmRjIn0.ew0KICJpc3MiOiAiczZCaGRSa3.... \
&client_id=myClient \
&scope=openid \
&response_type=code%20id_token \
&nonce=abc123 \
&state=123abc

Note that the URL is split for readability purposes.

Required: No. OIDC flows and JAR specification requests only.

request_uri

Specifies a reference to one or more base64-encoded JWTs, according to the context of the authorization flow:

  • For PAR flows, this parameter references the request data specified when the PAR endpoint was invoked by the client.

    AM rejects the authorization request if the request URI has expired.

  • For OIDC flows and JAR requests, this parameter specifies an array of URIs from which AM can retrieve JWTs whose claims constitute the request parameters. For information about the JWT, see the request parameter.

    The URI must be pre-registered in the Requests uris field (Realms > Realm Name > Applications > OAuth 2.0 > Clients > Client Name > Advanced).

    Each of the request URIs must not exceed 512 ASCII characters and must use either HTTP or HTTPS. For example, https://www.example.com:8443/JTWs/myJWT.

    AM caches the retrieved JWT to avoid fetching it too often. To force AM to flush the cache, add a unique fragment to the request_uri parameter. For example, ?request_uri=https://www.example.com:8443/JTWs/myJWT#foo.

    Required: No, only if PAR is required. PAR, OIDC and JAR specification requests only.

/oauth2/bc-authorize

The /oauth2/bc-authorize endpoint is the backchannel authorization endpoint as used by OpenID Connect Client Initiated Backchannel Authentication Flow - Core 1.0 draft-02. Use this endpoint to initiate backchannel authorization with the resource owner when using the following flow:

You must compose the path to the backchannel authorization endpoint addressing the specific realm where the authorization request ID will be issued. For example, https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/bc-authorize.

The endpoint supports the following parameters:

client_id

Specifies the client ID unique to the application making the request.

Required: Yes.

client_secret

Specifies the password of the private client making the request. Do not use in conjunction with the cnf_key parameter.

Required: A form of password or credentials is required for confidential clients. However, the use of the client_secret parameter depends on the client authentication method used. For more information, see OAuth 2.0 client authentication.

client_assertion

Specifies the signed JWT that the client uses as a credential when using the JWT bearer client authentication method.

For more information, see OAuth 2.0 client authentication.

Required: Yes, when using the JWT bearer client authentication method.

client_assertion_type

Specifies the type of assertion when the client is authenticating to the authorization server using JWT bearer client authentication. Do not use with other client authentication methods.

Set it to urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer.

For more information, see OAuth 2.0 client authentication.

Required: Yes, when using the JWT bearer client authentication method.

The endpoint requires a signed JWT that contains the following parameters:

aud

Specifies a string or an array of strings that is the intended audience of the JWT. Must be set to the authorization server’s OAuth 2.0 endpoint, for example:

"aud": "http://openam.example.com:8080/openam/oauth2"
exp

Specifies the expiration time of the JWT in Unix time.

Providing a JWT with an expiry time greater than 30 minutes causes AM to return a JWT expiration time is unreasonable error message.

iss

Specifies the unique identifier of the JWT issuer.

The identifier must match the client ID of the OAuth 2.0 client in AM, for example myCIBAClient.

login_hint

Specifies the principal who is the subject of the JWT. It should be a string that identifies the resource owner.

You can provide a previously obtained ID token in a property named id_token_hint as the hint for determining the resource owner, rather than a string.

scope

Specifies a space-separated list of the requested scopes. Must include the openid scope.

acr_values

Specifies an identifier that maps to the authentication mechanism AM uses to obtain authorization from the end user.

binding_message

Specifies a message delivered to the user when obtaining authorization.

Should be a short (100 characters or fewer), description of the operation the end user is authorizing, and should include an identifier to match the authorization request to the client that initiated the request.

If the binding message is sent using push notifications, the following additional limitations apply to the value:

  1. Must begin with a letter, number, or punctuation mark.

  2. Must not include line breaks or control characters.

For example: Allow ExampleBank to transfer £50 from your 'Main' account to your 'Savings' account? (EB-0246326)

/oauth2/access_token

The /oauth2/access_token endpoint is the OAuth 2.0 token endpoint as defined in RFC 6749. Use this endpoint to acquire an access or refresh token when using the following flows:

You must compose the path to the token endpoint addressing the specific realm where the token will be issued. For example, https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/token.

The token endpoint supports the following parameters:

grant_type

Specifies the type of grant to send to the authorization server to acquire an access token.

The following types are supported:

  • password, for the resource owner password credentials grant flow.

  • authorization_code, for the authorization code grant (OAuth 2.0) | OpenID Connect) grant flows.

  • client_credentials, for the Client credentials grant flow.

  • urn:ietf:params:oauth:grant-type:device_code, for the Device flow. An earlier specification, http://oauth.net/grant_type/device/1.0, is also supported.

  • urn:openid:params:grant-type:ciba, for the client-initiated backchannel authentication (CIBA) flow. For more information, see Backchannel request grant.

  • refresh_token, to refresh an access token. For more information, see Refresh tokens.

  • urn:ietf:params:oauth:grant-type:saml2-bearer, for the SAML v2.0 profile for authorization grant. For more information, see SAML v2.0 profile for authorization grant.

  • urn:ietf:params:oauth:grant-type:jwt-bearer, for the JWT profile for OAuth 2.0 authorization grant. For more information, see JWT profile for OAuth 2.0 authorization grant.

Required: Yes

client_id

Specifies the client ID unique to the application making the request.

Required: Yes.

client_secret

Specifies the secret of the client making the request. Do not use in conjunction with the cnf_key parameter.

Required: A form of password or credentials is required for confidential clients. However, the use of the client_secret parameter depends on the client authentication method used. For more information, see OAuth 2.0 client authentication.

cnf_key

Specifies a base64-encoded JWK used to support JWK-based proof-of-possession.

Do not use in conjunction with the client_secret parameter.

Required: Yes, when using JWK proof-of-possession.

username

Specifies the username of the resource owner during the Resource Owner Credentials grant flow.

Required: Yes, when grant_type is set to password.

password

Specifies the password of the resource owner during the Resource Owner Credentials grant flow.

Required: Yes, when grant_type is set to password.

code

Specifies the authorization code obtained during the authorization code grant and authorization code with PKCE grant flows.

Required: Yes, when grant_type is set to authorization_code.

device_code

Specifies a device code obtained when requesting a user code during the device flow.

Required: Yes, when grant_type is set to urn:ietf:params:oauth:grant-type:device_code.

client_assertion

Specifies the signed JWT that the client uses as a credential when using the JWT bearer client authentication method.

For more information, see OAuth 2.0 client authentication.

Required: Yes, when using the JWT bearer client authentication method.

client_assertion_type

Specifies the type of assertion when the client is authenticating to the authorization server using JWT bearer client authentication. Do not use with other client authentication methods.

Set it to urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer.

For more information, see OAuth 2.0 client authentication.

Required: Yes, when using the JWT bearer client authentication method.

assertion

Specifies a SAML v2.0 assertion. The assertion must be first base64-encoded, and then URL encoded. For more information, see SAML v2.0 profile for authorization grant.

Required: Yes, when using the SAML v2.0 profile for authorization grant.

redirect_uri

The URI to return the resource owner to after authorization is complete. Must match the redirect_uri configured in the client profile registered with AM, and the redirect_uri set when requesting authorization.

The URI must be an absolute URI, and must not contain a fragment component. For example, https://www.example.com:443/callback/.

Required: Yes, when grant_type is set to authorization_code and it was included in the authorization code grant, and during the Implicit grant.

code_verifier

Specifies a random string that correlates the authorization request to the token request in the authorization code with PKCE grant flow.

Required: Yes, when requesting an access code in the authorization code grant with PKCE flow.

scope

Specify the scopes linked to the permissions requested by the client from the resource owner. If not specified, the default scopes specified in the client or the authorization server are requested.

Note that some grant flows, such as the authorization code grant, do not call the token endpoint with the scope. The scope is already defined in the authorization code. For details, see the specific grant flow documentation in OAuth 2.0 grant flows.

For more information, see OAuth 2.0 scopes and Claims.

Required: No.

auth_chain

Overrides the authentication tree configured for the realm, and also the tree configured in the OAuth 2.0 service in the realm, when supporting the Resource Owner Credentials grant flow.

By default, the Resource Owner Password Credentials grant flow uses the default authentication tree in the relevant realm.

The selected tree must be configured for requiring username and password only, without UI-based interaction from the resource owner. For example, using the ldapService chain or Example tree. If this is not the case, the server returns an HTTP 500 error message.

Required: No.

refresh_token

Specifies the refresh token that will be used to refresh an access token.

For more information, see Refresh tokens.

Required: No, only when refreshing access tokens.

/oauth2/device/code

The Device flow endpoint as defined by RFC 8628.

Client devices use this endpoint to present a user code to the resource owner that can be exchanged for an access token in the following flows:

You must compose the path to the device code endpoint addressing the specific realm where the user code will be issued. For example, https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/code.

The device code endpoint supports the following parameters:

client_id

Specifies the client ID unique to the application making the request.

Required: Yes.

state

Value to maintain state between the request and the callback. During authentication, the client sends this parameter to the authorization server. The authorization server must send it back unchanged in the response.

The application should use this value to ensure the response belongs to the user that initiated the requests, which mitigates CSRF attacks.

The value of state is typically a base64-encoded string that contains user state and that is unique to a user and their request.

Required: No, but it is strongly recommended.

scope

The scopes attached to the permissions requested from the resource owner by the client. If not specified, the default scopes specified in the client or the authorization server are requested.

Required: No, providing default scopes are defined in the OAuth 2.0 client configuration.

code_challenge

Specifies a string derived from the code verifier that is sent in the authorization request during the device flow with PKCE.

Required: Yes, when obtaining a user code in the device flow with PKCE.

code_challenge_method

Contains the method used to derive the code challenge. Possible values are plain and S256. When unset, it defaults to plain.

Required: Yes, when obtaining a user code in the device with PKCE Flow.

nonce

String value that associates the client session with the ID Token that also mitigates against replay attacks.

Required: No. OpenID Connect flows only.

acr_values

Authentication Context class Reference values used to communicate acceptable authentication trees.

Required: No. OpenID Connect flows only.

prompt

A space-separated, case-sensitive list of ASCII values that specifies whether AM should prompt the end user for authentication and consent. Possible values are:

  • none. AM does not display authentication or consent pages.

  • login. AM prompts the end user to authenticate.

  • consent. AM prompts the end user to grant consent.

Required: No. OpenID Connect flows only.

ui_locales

Specifies a space-separated list of the end user preferred languages for the user interface, ordered by preference. For example, en fr-CA fr.

Required: No. OpenID Connect flows only.

login_hint

String value indicating the ID to use for login.

When provided as part of the OpenID Connect Authentication Request, the login_hint is set as the value of a cookie named oidcLoginHint, which is an HttpOnly cookie (only sent over HTTPS).

For more information, see GSMA Mobile Connect.

Required: No. OpenID Connect flows only.

claims

Specifies a JSON object containing specific attributes about users to be returned in the ID Token.

Required: No. OpenID Connect flows only.

/oauth2/device/user

Device flow AM-specific endpoint for user interaction. Client devices use this endpoint to exchange a user code with consent from the resource owner to access the resources in the following flows:

You must compose the path to the device user endpoint addressing the specific realm where consent will be granted. For example, https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/device/user.

The device user endpoint supports the following parameters:

user_code

Specify the scopes linked to the permissions requested by the client to the resource owner. If not specified, the default scopes specified in the client or the authorization server are requested.

Required: Yes.

csrf

When interacting with the OAuth 2.0 consent page, this parameter helps prevent against cross-site request forgery (CSRF) attacks.

The parameter duplicates the contents of the tenant session cookie, <session-cookie-name>, which contains the SSO token of the resource owner giving consent.

When using the AM consent pages, this parameter is set in the consent page once the resource owner has authenticated, and it is sent to AM along with the consent.

When replacing AM consent pages with your own consent pages or when trying the flows without a browser, you must set this parameter manually. For an example of a curl command, see the Authorization code grant.

Required: Yes, for calls that are submitting consent response, unless you use the Remote Consent Service to gather consent.

scope

Specify the scopes linked to the permissions requested by the client to the resource owner. If not specified, the default scopes specified in the client or the authorization server are requested.

Required: No.

decision

Specifies whether the resource owner consents to the requested access. Set to allow to grant consent. Any other value denies consent.

Required: Yes, to submit consent on non-interactive calls, unless consent is already saved for the scope.

save_consent

Updates the resource owner’s profile to avoid having to prompt the resource owner to grant authorization when the client issues subsequent authorization requests.

Set this parameter to on to save the consent.

To save the consent, you must have configured the Saved Consent Attribute Name property with a profile attribute in which to store the resource owner’s consent decision.

For more information on setting this property in the OAuth 2.0 provider service, see OAuth2 Provider.

Required: No.

/oauth2/token/revoke

Endpoint defined in RFC7009 - Token Revocation, used to revoke both access and refresh tokens.

Revoking a refresh token also revokes any other associated tokens that were issued with the same authorization grant. If a client has multiple access tokens for a single user that were obtained using different authorization grants, the client would need to make multiple calls to the revoke token endpoint to invalidate each token.

The revoke token endpoint supports the following parameters:

token

Specifies the token ID that will be revoked.

Required: Yes.

client_id

Specifies the client ID unique to the application making the request.

Required: Yes.

client_secret

Specifies the password of the private client making the request. Do not use in conjunction with the cnf_key parameter.

Required: A form of password or credentials is required for confidential clients. However, the use of the client_secret parameter depends on the client authentication method used. For more information, see OAuth 2.0 client authentication.

client_assertion

Specifies the signed JWT that the client uses as a credential when using the JWT bearer client authentication method.

For more information, see OAuth 2.0 client authentication.

Required: Yes, when using the JWT bearer client authentication method.

client_assertion_type

Specifies the type of assertion when the client is authenticating to the authorization server using JWT bearer client authentication. Do not use with other client authentication methods.

Set it to urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer.

For more information, see OAuth 2.0 client authentication.

Required: Yes, when using the JWT bearer client authentication method.

You must compose the path to the revoke token endpoint addressing the specific realm where the user code was issued. For example, https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/revoke.

The following is an example of how to revoke a given token:

$ curl --request POST \
--data "token=xS3UjtuXMu77iNzl2XibpeMlw1g" \
--data "client_id=myClient" \
--data "client_secret=forgerock" \
"https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/token/revoke"
{}

/oauth2/introspect

Endpoint defined in RFC7662 - OAuth 2.0 Token Introspection, used to retrieve metadata about a token, such as approved scopes, the user that authorized the token, the expiry time, the UMA RPT, or the proof-of-possession JWK.

The /oauth2/introspect endpoint requires the resource server to authenticate to the authorization server.

Introspecting special tokens

  • To introspect macaroon access tokens containing third-party caveats, use the X-Discharge-Macaroon header to pass the discharge macaroon.

  • To introspect UMA RPT tokens, use the PAT of the resource owner in an authorization: Bearer header to authenticate to the endpoint.

The token introspection endpoint supports the following parameters:

token

Specifies the token ID.

Required: Yes.

client_id

Specifies the client ID unique to the application making the request.

Required: A form of credentials is required for confidential clients. However, the use of the client_id parameter depends on the client authentication method used. For more information, see OAuth 2.0 client authentication.

client_secret

Specifies the secret of the client making the request.

Required: A form of password or credentials is required for confidential clients. However, the use of the client_secret parameter depends on the client authentication method used. For more information, see OAuth 2.0 client authentication.

client_assertion

Specifies the signed JWT that the client uses as a credential when using the JWT bearer client authentication method.

For more information, see OAuth 2.0 client authentication.

Required: Yes, when using the JWT bearer client authentication method.

client_assertion_type

Specifies the type of assertion when the client is authenticating to the authorization server using JWT bearer client authentication. Do not use with other client authentication methods.

Set it to urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer.

For more information, see OAuth 2.0 client authentication.

Required: Yes, when using the JWT bearer client authentication method.

You must compose the path to the introspect endpoint addressing the specific realm where the token was issued. For example, https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/introspect.

By default, and for security reasons, clients can only introspect their own tokens. To let a client introspect access tokens issued to other clients, see Special Scopes.

The following example shows AM returning token information:

$ curl \
--request POST \
--header "Authorization: Basic ZGVtbzpDaDRuZzMxdA==" \
--data "token=f9063e26-3a29-41ec-86de-1d0d68aa85e9" \
"https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/introspect"
{
    "active": true,
    "scope": "write",
    "client_id": "myClient",
    "user_id": "demo",
    "username":"demo",
    "token_type": "Bearer",
    "exp": 1419356238,
    "sub": "(usr!demo)",
    "subname" : "demo",
    "iss": "https://<tenant-name>.forgeblocks.com/am/oauth2"
    "cnf": {
        "jwk": {
            "alg": "RS512",
            "e": "AQAB",
            "n": "k7qLlj…​G2oucQ",
            "kty": "RSA",
            "use": "sig",
            "kid": "myJWK"
        },
    "auth_level": 0
    }
}

The introspection response, as specified in RFC7662, is a plain JSON object. However, AM also supports the JWT Response for OAuth Token Introspection Internet Draft, which adds signed JWT or signed then encrypted JWT responses.

To configure the response type, perform the following steps:

  1. Go to Realms > Realm Name > Applications > OAuth 2.0 > Clients > Client Name > Signing and Encryption.

  2. In the Token introspection response format drop-down list, select the type of response required by the client.

  3. Configure the signing and/or encryption settings AM should use when returning introspection responses to this particular client in the following properties:

    • Token introspection response signing algorithm

    • Token introspection response encryption algorithm

    • Token introspection encrypted response encryption algorithm

    For more information about these properties, see Signing and encryption properties.

Even if the client has configured the response to be JSON-formatted, it can request a signed JWT by adding the "Accept: application/jwt" header to the request.

For example:

$ curl \
--request POST \
--header "Accept: application/jwt" \
--header "Authorization: Basic ZGVtbzpDaDRuZzMxdA==" \
--data "token=f9063e26-3a29-41ec-86de-1d0d68aa85e9" \
"https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/introspect"

However, when a client that is configured to use either of the JWT-formatted responses requests a JSON response, AM returns an error.

The following is a list of the objects commonly returned by the token introspect endpoint:

active

Specifies whether the token is active (true) or not (false).

scope

Specifies a space-separated list of the scopes associated with the token.

client_id

Specifies the client that requested the token.

user_id

(Deprecated, defined in a previous draft of the spec) Specifies the user that authorized the token.

username

Specifies the user that authorized the token.

token_type

Specifies the type of token.

exp

Specifies the token expiration time in seconds since January 1 1970 UTC.

expires_in

Specifies the time, in seconds, that the token is valid for. This value is set at token creation time, and it depends on the configuration of the OAuth2 Provider Service.

During the introspection call, AM calculates the amount of seconds the token is still valid for and returns it in the expires_in object. Therefore, repeated calls to the endpoints return different values for the object.

However, the actual value of the expires_in object in the token does not change. Inspecting the token without using AM will show the value set at token creation time.

AM only returns this object for client-based tokens issued to a client configured in the same realm that the resource owner’s.

sub

Specifies the identifier of the identity or the OAuth 2.0/OpenID Connect client, that is the subject of the access token.

The subject claim is in the format (type!subject), where:

  • subject is the identifier of the user/identity, or the name of the OAuth 2.0/OpenID Connect client that is the subject of the token.

  • type can be one of the following:

    • age. Specifies that the subject is an OAuth 2.0/OpenID Connect-related user-agent or client. For example, an OAuth 2.0 client, a Remote Consent Service agent, and a Web and Java Agent internal client.

    • usr. Specifies that the subject is a user/identity.

For example, (usr!demo), or (age!myOAuth2Client).

iss

Specifies the issuer of the token.

cnf

Specifies the confirmation key claim containing one of the following key types:

  • jwk, which contains the decoded JSON web key (JWK) associated with the access token. For more information, see the JWK-based proof-of-possession flow.

macaroon

Specifies the macaroon validated by the token, including any caveats appended to the macaroon.

auth_level

(AM-specific extension property) Specifies the authentication level of the resource owner that authenticated to authorize the token.

permissions

(UMA only). Specifies an array that contains the RPT token expiration time (exp), the resource scopes of the token, and the resource ID.

/json/token/macaroon

AM’s macaroon endpoint can be used to inspect and manipulate macaroons. Macaroons are designed to be manipulated locally using a macaroon library. This can be done securely by anybody in possession of the macaroon token without needing access to any keys at all.

AM’s macaroon endpoint supports two actions:

  • inspect: returns details about the macaroon.

  • restrict: adds a new caveat to the macaroon, returning a new macaroon.

You must compose the path to the introspect endpoint addressing the specific realm where the token was issued. For example, https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/token/macaroon/?_action=inspect.

The following example shows AM returning macaroon information:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "cache-control: no-cache" \
--data '{
    "macaroon":"AgEAAhtCRDFJSGhhLUktU21VbE5EQ0Y4MXVQRmlzUFUAAAYgnKhrEUFDwEwSPeTHwRSwTss7a4V0W68nL5Xw-nnRhzQ"
    }' \
"https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/token/macaroon?_action=inspect"
{
  "identifier": "1bmn1TQTONczbom-V2lCpaH4BUk",
  "location": "",
  "caveats": [
      {
        "type": "first-party",
        "identifier": {
         "scope": "openid profile"
        }
      }
  ],
   "signature": "kmVBwqpoi4nwakksk3b8KcSZvlYYmjCPdUTrFKFnhEY"
}

OpenID Connect clients must ensure that the following information is present in the JSON:

  • The openid scope. For example, "scopes": ["profile", "openid"].

  • The id_token response type. For example, "response_types": ["code", "id_token code"].

/oauth2/tokeninfo (Legacy)

AM-specific endpoint used to validate tokens and to retrieve information out of them, such as scopes, the grant type used when issuing the token, or the token expiration time.

The /oauth2/tokeninfo endpoint is labelled as legacy.

To validate tokens and retrieve information with a spec-based endpoint, see /oauth2/introspect.

Resource servers—or any party having the token ID—can obtain token information through this endpoint without authenticating.

The token information endpoint supports the following query parameter:

access_token

Specifies the token ID.

Required: Yes.

The following example shows AM issuing an access token, and then returning token information:

$ curl --request POST \
--data "grant_type=password" \
--data "username=demo" \
--data "password=Ch4ng31t" \
--data "scope=write" \
--data "client_id=myClient" \
--data "client_secret=forgerock" \
"https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"
{
  "access_token": "sbQZuveFumUDV5R1vVBl6QAGNB8",
  "scope": "write",
  "token_type": "Bearer",
  "expires_in": 3599
}
$ curl \
--request GET \
--header "Authorization: Bearer sbQZuveFumUDV5R1vVBl6QAGNB8" \
"https://<tenant-name>.forgeblocks.com/am/oauth2/tokeninfo"
{
   "access_token":"sbQZuveFumUDV5R1vVBl6QAGNB8",
   "grant_type":"password",
   "auth_level":0,
   "scope":[
      "write"
   ],
   "realm":"/alpha",
   "token_type":"Bearer",
   "expires_in":2491,
   "write":"",
   "client_id":"myClient"
}

Note that AM returns a JSON object with the following properties:

access_token

Specifies the token ID.

grant_type

Specifies the OAuth 2.0 grant flow used to issue the token.

auth_level

Specifies the authentication level of the resource owner that authenticated to authorize the token.

scope

Specifies a JSON structure containing the scopes associated with the token.

realm

Specifies the realm from which the token was obtained.

token_type

Specifies the type of token.

expires_in

Specifies the time, in seconds, that the token is valid for. This value is set at token creation time, and it depends on the configuration of the OAuth2 Provider service.

During the introspection call, AM calculates the amount of seconds the token is still valid for and returns it in the expires_in object. Therefore, repeated calls to the endpoints return different values for the object.

However, the actual value of the expires_in object in the token does not change. Inspecting the token without using AM will show the value set at token creation time.

AM does not return this object for client-side tokens issued to a client configured in a different realm that the resource owner’s.

client_id

Specifies the client that requested the token.

OAuth 2.0 administration REST endpoints

AM exposes the following administration and supporting REST endpoints:

Table 5. OAuth 2.0 administration and supporting endpoints
Endpoint Description

Register, list, and delete OAuth 2.0 clients (AM specific-endpoint)

List OAuth 2.0 clients holding active tokens granted by specific resource owners, and delete tokens for a combination of resource owner and client (AM-specific endpoint)

/json/realm-config/agents/OAuth2Client

AM-specific endpoint that lets AM and agent administrators create, list, and delete OAuth 2.0 clients.

Use the AM API explorer for detailed information about the parameters supported by this endpoint, and to test it against your deployed AM instance.

In the AM admin UI, click the Help icon, and go to API Explorer > /realm-config > /agents > /OAuth2Client.

The following example shows how to create a basic OAuth 2.0 client named myClient in a realm named alpha. Note that you must provide the SSO token of an administrative user as a header, and that the name of the client is appended to the URL:

$ curl \
 --request PUT \
 --header "Accept-API-Version: resource=1.0" \
 --header "Content-Type: application/json" \
 --header "Accept: application/json" \
 --header "<session-cookie-name>: AQIC5wM…​3MTYxOA..*" \
--data '{
   "coreOAuth2ClientConfig":{
      "agentgroup":"",
      "status":{
         "inherited":true,
         "value":"string"
      },
      "userpassword":"forgerock",
      "clientType":{
         "inherited":false,
         "value":"Confidential"
      },
      "redirectionUris":{
         "inherited":false,
         "value":[
            "https://www.example.com:443/callback"
         ]
      },
      "scopes":{
         "inherited":false,
         "value":[
            "write",
            "read"
         ]
      },
      "defaultScopes":{
         "inherited":true,
         "value":[
            "write"
         ]
      },
      "clientName":{
         "inherited":true,
         "value":[
            "My Test Client"
         ]
      }
   },
   "advancedOAuth2ClientConfig":{
      "name":{
         "inherited":false,
         "value":[
            null
         ]
      },
      "grantTypes":{
         "inherited":true,
         "value":[
            "authorization_code",
            "client_credentials"
         ]
      },
      "tokenEndpointAuthMethod":{
         "inherited":true,
         "value":"client_secret_basic"
      }
   }
}' \
"https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/realm-config/agents/OAuth2Client/testClient"
{
   "_id":"testClient",
   "_rev":"-60716879",
   "advancedOAuth2ClientConfig":{
      "descriptions":{
         "inherited":false,
         "value":[

         ]
      },

…​

      "clientType":{
         "inherited":false,
         "value":"Confidential"
      },
…​
      "_type":{
      "_id":"OAuth2Client",
      "name":"OAuth2 Clients",
      "collection":true
   }
}

The following example shows how to delete an OAuth 2.0 client named myClient in realm named alpha. Note that you must provide the SSO token of an administrative user as a header, and that the name of the client is appended to the URL:

$ curl \
    --request DELETE \
    --header "Accept-API-Version: resource=1.0" \
    --header "<session-cookie-name>: AQIC5wM…​3MTYxOA..*" \
    "https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/realm-config/agents/OAuth2Client/myClient"
{
   "_id":"testClient",
   "_rev":"-60716879",
   "advancedOAuth2ClientConfig":{
      "descriptions":{
         "inherited":false,
         "value":[

         ]
      },

…​

      "clientType":{
         "inherited":false,
         "value":"Confidential"
      },
…​
      "_type":{
      "_id":"OAuth2Client",
      "name":"OAuth2 Clients",
      "collection":true
   }
}

You can use a similar PUT command to the one above to update an existing OAuth 2.0 client. However, ensure that you include all the attributes to be retained. Omitting an attribute in the resource amounts to deleting the attribute.

/users/user/oauth2/applications

AM-specific endpoint for listing clients holding tokens granted by specific resource owners, and for deleting tokens for a combination of a resource owner and client.

Use the AM API explorer for detailed information about the parameters supported by this endpoint, and to test it against your deployed AM instance.

In the AM admin UI, click the Help icon, and go to API Explorer > /users > /{user} > /oauth2 > /applications.

To call the endpoint, you must compose the path to the realm where the client is registered.

The following example shows how to list all the clients holding tokens granted in the alpha realm by the demo user. Note that you must provide the SSO token of an administrative user or of the resource owner as a header, and that the name of the resource owner (demo) is part of the URL:

$ curl --request GET \
--header "Accept-API-Version: resource=1.1" \
--header "<session-cookie-name>: Ua6fsH2vjgHqVY…​" \
"https://<tenant-name>.forgeblocks.com/am/realms/root/realms/alpha/json/users/demo/oauth2/applications?_queryFilter=true"

On success, AM returns an HTTP 200 code and a JSON structure containing information about the tokens, such as the client ID they belong to, the granted scopes, and their expiration time:

{
   "result":[
      {
         "_id":"myClient",
         "_rev":"22274676",
         "name":null,
         "scopes":{
            "write":"write"
         },
         "expiryDateTime":"2018-11-14T10:48:55.395Z",
         "logoUri":null
      }
   ],
   "resultCount":1,
   "pagedResultsCookie":null,
   "totalPagedResultsPolicy":"NONE",
   "totalPagedResults":-1,
   "remainingPagedResults":-1

The following example shows how to delete all tokens held by the client myClient granted in the alpha realm by the demo user. Note that you must provide the SSO token of an administrative user or of the resource owner as a header, and that the name of the resource owner (demo) and the name of the client (myClient) are part of the URL:

$ curl --request DELETE \
--header "Accept-API-Version: resource=1.1" \
--header "<session-cookie-name>: Ua6fsH2vjgHqVY…​" \
"https://<tenant-name>.forgeblocks.com/am/realms/root/realms/alpha/json/users/demo/oauth2/applications/myClient"

On success, AM returns an HTTP 200 code and a JSON structure containing information about the deleted tokens, such as the client ID they belonged to, the scopes they granted, and their expiration time:

{
  "_id": "myClient",
  "_rev": "22274676",
  "name": null,
  "scopes": {
    "write": "write"
  },
  "expiryDateTime": "2018-11-14T10:48:55.395Z",
  "logoUri": null
}

Customize OAuth 2.0 with plugins

AM includes several plugin points that let you extend OAuth 2.0 authorization server functionality, such as modifying access tokens or customizing how AM processes scopes.

Supported plugin points

The following table describes the OAuth 2.0 plugin points supported in AM.

Plugin Description

Modify the OAuth2 access token before the token is persisted or returned to the client.

Return additional data from an authorization request.

Evaluate and return an OAuth2 access token’s scope information.

Customize the set of requested scopes for authorize, access token, refresh token, and back channel authorize requests.

Fetch the resource owner’s information based on an issued access token.

How to build and use a custom OAuth 2.0 plugin

AM supports scripted custom plugins that are written in JavaScript. The following sections describe how to deploy a custom plugin.

Customize with a plugin script

AM provides a scripting engine and template scripts for you to extend OAuth 2.0 behavior by running scripts stored as configuration, rather than by updating code. Creating and modifying plugin scripts enables rapid development without the need to change or recompile core AM.

Create or modify an OAuth 2.0 plugin script

To create or edit a script that is saved for the current realm, you can use the AM admin UI. The sample scripts provide a good starting point for you to develop your own custom implementation.

For more information see The Scripting Guide.

Configure AM to use an OAuth 2.0 plugin script

After creating your plugin script, you need to configure AM to use the plugin.

  1. In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Plugins to configure a specific OAuth 2.0 provider.

  2. Set the Plugin Type attribute to SCRIPTED.

  3. Set the Script attribute to the name of the script you want to use.

    For example, for the scope validation plugin, select the name of your script from the Scope Validation Script drop-down list. This list contains all the scripts that are saved for the current realm for the particular plugin type, including the default scripts that AM provides. In the case of the scope validation plugin, the list displays all scripts of type OAuth2 Validate Scope.

    For further details about plugin configuration, see OAuth2 Provider Plugins.

  4. Save your changes.

OAuth 2.0 scripting API

The following properties are common to all OAuth 2.0 scripts. See individual plugins for additional properties specific to the script type.

Show script properties
httpClient

The HTTP client for making external HTTP requests. Always present.

logger

The logger instance particular to the script type. The output log files will be prefixed by a static string denoting the script type. Always present.

scriptName

The display name of the script. Always present.

Access token modification plugin

Use this extension point to modify the key-value pairs in an OAuth 2.0 access token. For example, you could make a REST call to an external service, and add or change a key-value pair in the access token based on the response, before issuing the token to the resource owner.

To view the sample script, including the available script properties, see oauth2-access-token-modification.groovy.

Modify access tokens

You can modify both stateless and stateful access tokens. Modifications are stored permanently in either the issued JWT for stateless tokens, or in the CTS for stateful access tokens. You can also modify macaroons used in place of regular tokens. In this case, you implement the plugin to modify the key pairs in the token, and optionally, to add caveats.

When issuing modified access tokens, consider the following important points:

  • Removing or changing native properties may render the access token unusable.

    AM requires that certain native properties are present in the access token in order to consider it valid. Removing or modifying these properties may cause the OAuth 2.0 flows to break.

  • Modifying access tokens affects the size of the stateless token or stateful entry.

    Changes made to OAuth 2.0 access tokens directly impacts the size of the stateful tokens, or the size of the JSON web tokens (JWT) if stateless tokens are enabled.

    You must ensure that the token size remains within your client or user-agent size limits.

    For more information, see Token storage location.

Example access token modification plugin

Complete the following steps to implement a custom access token modification script that sets additional properties in the access token:

Prepare the access token modification script

The script requires that the authenticated user of the access token has an email address and telephone number in their profile. The script adds the values of these fields to the access token.

  1. Log in to the AM admin UI as an administrator.

  2. Add an email address and telephone number value to a user profile.

    For this example, the user has the ID demo.

    The access token modification script injects the values provided into the OAuth 2.0 access token before it is issued to the resource owner:

    1. Select Realms > Realm Name > Identities.

    2. On the Identities tab, select the demo user.

    3. In Email Address, enter a valid address. For example, demo.user@example.com.

    4. In Telephone Number, enter a value. For example, 44 117 496 0228.

    5. Save your changes.

  3. Modify the template access token modification script to set additional fields.

    1. Go to Realms > Realm Name > Scripts, and click New Script.

  4. Enter a unique name for your script, select OAuth2 Access Token Modification from the Script Type drop-down list, and click Create.

    1. In the Script field:

      • Uncomment the following line (line 74), by surrounding with a pair of */ and /* strings:

        /* ... */
        accessToken.setField('key1', 'value1');
        /* ... */
      • Similarly, uncomment these lines (116-117):

        /* ... */
        accessToken.setField('mail', identity.getAttribute('mail'));
        accessToken.setField('phone', identity.getAttribute('telephoneNumber').toArray()[0]);
        /* ... */
    2. Save your changes.

Configure AM to use the custom access token modification script

Perform this task to set up an OAuth 2.0 provider that uses the modified default access token modification script.

  1. Log in to the AM admin UI as an administrator.

  2. Configure the OAuth2 Provider:

    • If no provider exists for the current realm, create a new OAuth 2.0 provider:

      1. Go to Realms > Realm Name > Services and click Add a Service.

      2. Select OAuth2 Provider service from the drop-down list, leave the fields unchanged, and click Create.

    • Otherwise, go to Realms > Realm Name > Services > OAuth2 Provider.

      The OAuth2 provider configuration is displayed.

      For information on OAuth 2.0 provider properties, see OAuth2 Provider.

      By default, a new OAuth 2.0 provider uses the template access token modification script.

  3. For existing providers, select the Plugins tab to ensure the following settings are configured correctly:

    1. Set Access Token Modification Plugin Type to SCRIPTED.

    2. Set Access Token Modification Plugin Script to OAuth2 Access Token Modification Script.

  4. Save your changes.

Create an OAuth2 client for authorization

Create an OAuth 2.0 client to use in the authorization request.

  1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.

  2. Enter the following values:

    • Client ID: myClient

    • Client secret: forgerock

    • Redirection URIs: https://www.example.com:443/callback

    • Scope(s): access|Access to your data

  3. Click Create.

AM is now configured to issue access tokens using the default access token modification script. As the demo user, you can now obtain an access token to test the script functionality.

Try the custom access token modification script

This section describes how to retrieve an OAuth 2.0 access token that has been modified by a script.

First, use the Authorization code grant flow to authenticate with AM as the resource owner, let the client access profile data, and receive the authorization code.

Next, exchange the authorization code for an access token.

The access token will have been altered by the default access token modification script to include:

  • The resource owner’s telephone number and email address, taken from their profile in AM, which is acting as the authorization server.

  • A key1:value1 key-value pair.

Finally, use the introspect endpoint to verify that the access token includes the modified values.

Get an authorization code
  1. In a web browser, go to the /oauth2/authorize endpoint, including the parameters and values configured for the OAuth 2.0 client in the previous section.

    Make sure you specify the correct realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the /alpha realm, then use /oauth2/realms/root/realms/alpha/authorize.

    For example:

    https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize \
    ?client_id=myClient \
    &response_type=code \
    &scope=access \
    &state=abc123 \
    &redirect_uri=https://www.example.com:443/callback

    Note that the URL is split for readability purposes.

    The AM login page is displayed.

  2. Log in as the demo user, with password Ch4ng31t.

    The AM OAuth 2.0 consent page is displayed.

  3. Review the scopes being requested, and click Allow.

    AM redirects the browser to the location specified in the redirect_uri parameter, https://www.example.com:443/callback in this example, and appends a number of query parameters.

    For example:

    OAuth 2.0 authorization code in browser URL bar.
  4. Record the value of the code query parameter.

    This is the authorization code and is exchanged for an access token in the next procedure.

Exchange an authorization code for an access token
  1. Send a POST request to the /oauth2/access_token endpoint, including the authorization code obtained in the previous procedure, and the parameters and values configured for the OAuth 2.0 client earlier.

    For example:

    $ curl --request POST \
      --data "grant_type=authorization_code" \
      --data "code=tH_s2obVRt2_yB6x4OxH1J3eMkU" \
      --data "client_id=myClient" \
      --data "client_secret=forgerock" \
      --data "redirect_uri=https://www.example.com:443/callback" \
      "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token"
    {
      "access_token": "sbQZuveFumUDV5R1vVBl6QAGNB8",
      "scope": "access",
      "token_type": "Bearer",
      "expires_in": 3599
    }
  2. Record the value of the access_token property.

    This is the access token, the properties of which have been modified by the access token modification script. Follow the steps in the next procedure to introspect the token to verify the properties have been modified.

Introspect an access token to verify access token modification
  1. Send a POST request to the /oauth2/introspect endpoint, including the access token obtained in the previous procedure, and the credentials of the OAuth 2.0 client.

    For example:

    $ curl \
      --request POST \
      --data "client_id=myClient" \
      --data "client_secret=forgerock" \
      --data "token=sbQZuveFumUDV5R1vVBl6QAGNB8" \
      "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/introspect"
    {
      "active": true,
      "scope": "access",
      "client_id": "myClient",
      "user_id": "demo",
      "username":"demo",
      "token_type": "Bearer",
      "exp": 1556289970,
      "sub": "(usr!demo)",
      "subname": "demo",
      "iss": "https://<tenant-name>.forgeblocks.com/am/oauth2",
      "auth_level": 0,
      "auditTrackingId": "c6e22be7-6166-402b-9d72-a03134f08c22-8605",
      "key1": "value1",
      "mail": [
        "demo.user@example.com"
      ],
      "phone": [
        "+44 117 496 0228"
      ]
    }

    Notice that the output includes a hello:world key-value pair, as well as mail and phone properties, containing values taken from the user’s profile data.

OAuth 2.0 access token modification scripting API

The following properties are available to access token modification scripts, in addition to the common OAuth 2.0 properties.

Show script properties
accessToken

The access token to be updated.

clientProperties

A map of properties configured in the relevant client profile. Only present if the client was correctly identified.

The keys in the map are as follows:

clientId

The URI of the client.

allowedGrantTypes

The list of the allowed grant types (org.forgerock.oauth2.core.GrantType) for the client.

allowedResponseTypes

The list of the allowed response types for the client.

allowedScopes

The list of the allowed scopes for the client.

customProperties

A map of any custom properties added to the client.

Lists or maps are included as sub-maps. For example, a custom property of customMap[Key1]=Value1 is returned as customMap > Key1 > Value1.

To add custom properties to a client, go to OAuth 2.0 > Clients > Client ID > Advanced, and then update the Custom Properties field.

requestProperties

A map of the properties present in the request. Always present.

The keys in the map are as follows:

requestUri

The URI of the request.

realm

The realm to which the request was made.

requestParams

The request parameters, and/or posted data. Each value in this map is a list of one, or more, properties.

To mitigate the risk of reflection-type attacks, use OWASP best practices when handling these properties. For example, see Unsafe use of Reflection.

scopes

Contains a set of the requested scopes. For example:

[
  "read",
  "transfer",
  "download"
]
session

Contains a representation of the user’s session object if the request contained a session cookie.

Authorize endpoint data provider plugin

Use this plugin to configure the OAuth2 provider to return additional data from an authorization request, such as data from the user’s session or from an external service.

To view a sample script, including the available script properties, see oauth2-authorize-endpoint-data-provider.js.

Example authorization endpoint data provider plugin

Complete the following steps to implement an authorization endpoint data provider script that returns custom user session data:

Prepare the authorization endpoint data provider script

This task decribes how to create a script to retrieve additional fields.

  1. In the AM admin UI, go to Realms > Realm Name > Scripts, and click New Script.

  2. Enter a unique name for your script, select OAuth2 Authorize Endpoint Data Provider from the Script Type drop-down list, and click Create.

  3. Copy the oauth2-authorize-endpoint-data-provider.js script and paste in the Script field.

    • Enable the script by removing, or commenting out as seen in this example, the following block comments surrounding the function, on lines 40 and 90:

      // /* EXAMPLE
      ...
      // */
    • For the purposes of this simple test, comment out the call to add data from a third-party service:

      //addAdditionalDataFromExternalService();
  4. Save your changes.

The template authorization endpoint data provider script is now amended to return a static key/value pair, "hello": "world", and to get the user’s IP address from the session data.

Configure AM to use the authorization endpoint data provider script

Perform this task to set up an OAuth2 provider to use the authorization endpoint data provider script.

  1. Log in to the AM admin UI as an administrator.

  2. Configure the OAuth2 Provider:

    • If no provider exists for the current realm, create a new OAuth 2.0 provider:

      1. Go to Realms > Realm Name > Services and click Add a Service.

      2. Select OAuth2 Provider service from the drop-down list, leave the fields unchanged, and click Create.

    • Otherwise, go to Realms > Realm Name > Services > OAuth2 Provider.

      The OAuth2 provider configuration is displayed.

      For information on OAuth 2.0 provider properties, see OAuth2 Provider.

  3. Select the Plugins tab to edit the following settings:

    1. Set Authorize Endpoint Data Provider Plugin Type to SCRIPTED.

    2. Set Authorize Endpoint Data Provider Script to the name of the script you created.

  4. Save your changes.

Create an OAuth2 client for authorization

Create an OAuth 2.0 client to use in the authorization request.

  1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.

  2. Enter the following values:

    • Client ID: myClient

    • Client secret: forgerock

    • Redirection URIs: https://www.example.com:443/callback

    • Scope(s): access|Access to your data

  3. Click Create.

AM is now prepared for you to perform an OAuth2 authorization request to try the sample plugin.

Try the sample authorization endpoint data provider plugin

  1. Log in to AM as the demo user, for example:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }

    Note the SSO token value returned as tokenId in the output.

  2. Invoke the authorization server’s /oauth2/authorize endpoint specifying the SSO token value in a cookie, and the following parameters:

    • client_id=myClient

    • response_type=code

    • redirect_uri=https://www.example.com:443/callback

    • decision=allow

    • csrf=SSO-token

    For example:

    $ curl --dump-header - \
    --request POST \
    --Cookie "iPlanetDirectoryPro=AQIC5wM…​TU3OQ*" \
    --data "scope=access" \
    --data "response_type=code" \
    --data "client_id=myClient" \
    --data "csrf=AQIC5wM…​TU3OQ*" \
    --data "redirect_uri=https://www.example.com:443/callback" \
    --data "state=abc123" \
    --data "decision=allow" \
    "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize"

    If the authorization server is able to authenticate the user and the client, it returns a successful HTTP 302 response, for example:

    HTTP/1.1 302 Found
    Server: Apache-Coyote/1.1
    X-Frame-Options: SAMEORIGIN
    Pragma: no-cache
    Cache-Control: no-store
    Date: Mon, 30 Jul 2018 11:42:37 GMT
    Accept-Ranges: bytes
    Location: https://www.example.com:443/callback?code=g5B3qZ8rWzKIU2xodV&ipAddress=127.0.0.1&scope=access&iss=https%3A%2F%2Fopenam.example.com%3A8443%2Fopenam%2Foauth2&hello=world&state=abc123&client_id=myClient
    Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
    Content-Length: 0

    As seen in the example output, the parameters injected by the authorization endpoint data provider script, ipAddress=127.0.0.1 and hello=world, are both appended to the redirect URL.

OAuth 2.0 authorization endpoint data provider scripting API

The following properties are available to authorization endpoint data provider scripts, in addition to the common OAuth 2.0 properties.

Show script properties
session

Contains a representation of the user’s session object if the request contained a session cookie.

Scope evaluator plugin

This extension point retrieves and evaluates the scope information for an OAuth2 access token.

The default scopes implementation in AM treats scopes as profile attributes for the resource owner. When a resource server or other entity uses the access token to get token information from AM, AM populates the scopes with profile attribute values. For example, if one of the scopes is mail, AM sets mail to the resource owner’s email address in the token information returned.

The plugin lets you extend or modify this behavior by writing your own scope evaluator plugin to populate the scopes with custom values.

To view a sample script, including the available script properties, see oauth2-evaluate-scope.js

Example scope evaluator plugin

Complete the following steps to implement a custom scope evaluator plugin.

Prepare the sample scope evaluator script

This task decribes how to create a script to map a custom value.

  1. In the AM admin UI, go to Realms > Realm Name > Scripts, and click New Script.

  2. Enter a unique name for your script, select OAuth2 Evaluate Scope from the Script Type drop-down list, and click Create.

  3. Copy the oauth2-evaluate-scope.js script and paste in the Script field.

  4. Update the script by inserting a custom key/value pair preceding return map; on line 50:

    map.put("hello", "world");
  5. Save your changes.

Configure AM to use the custom scope evaluator plugin

Perform this task to set up an OAuth 2.0 provider that uses the sample scope evaluator implementation.

  1. Log in to the AM admin UI as an administrator.

  2. Configure the OAuth2 Provider:

    • If no provider exists for the current realm, create a new OAuth 2.0 provider:

      1. Go to Realms > Realm Name > Services and click Add a Service.

      2. Select OAuth2 Provider service from the drop-down list, leave the fields unchanged, and click Create.

    • Otherwise, go to Realms > Realm Name > Services > OAuth2 Provider.

      The OAuth2 provider configuration is displayed.

      For information on OAuth 2.0 provider properties, see OAuth2 Provider.

  3. Select the Plugins tab to edit the following settings:

    1. Set Scope Evaluation Plugin Type to SCRIPTED.

    2. Set Scope Evaluation Script to the name of the script you created.

  4. Save your changes.

Create an OAuth2 client

Create an OAuth 2.0 client to use in the client credentials grant flow.

  1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.

  2. Enter the following values:

    • Client ID: myClient

    • Client secret: forgerock

    • Redirection URIs: https://www.example.com:443/callback

    • Scope(s): read write

  3. Click Create.

  4. In Advanced > Grant Types, add Client Credentials.

  5. Save your changes.

AM is now configured for you to try the sample scope evaluator script.

Try the custom scope evaluator Java plugin

To try the custom scope evaluator plugin, use the Client credentials grant flow.

  1. Send a POST request to the /oauth2/access_token endpoint, specifying the grant type as client_credentials, scope as read, and your client details.

    For example:

    $ curl \
    --request POST \
    --data "grant_type=client_credentials" \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data "scope=read" \
    "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/access_token"
    {
      "access_token": "M3M2Jb2SMjvgWhzNas2SVy2LALg",
      "scope": "read",
      "token_type": "Bearer",
      "expires_in": 3599
    }
  2. Call the /oauth2/tokeninfo (Legacy) endpoint to inspect the custom scope values. Include the access token obtained in the previous request.

    For example:

    $ curl \
    "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/tokeninfo\
    ?access_token=M3M2Jb2SMjvgWhzNas2SVy2LALg"
    {
      "access_token": "M3M2Jb2SMjvgWhzNas2SVy2LALg",
      "grant_type": "client_credentials",
      "auditTrackingId": "f9a8395d-1bac-4cba-8b09-8cc336dc49e2-6810",
      "scope": ["read"],
      "realm": "/alpha",
      "token_type": "Bearer",
      "expires_in": 3583,
      "authGrantId": "l3355H89FDSWsfdKJmvWssGk_oE",
      "hello": "world",
      "client_id": "myClient"
    }

    Verify that the response includes the custom key/value pair, "hello": "world".

OAuth 2.0 scope evaluator plugin scripting API

The following properties are available to scope evaluator scripts, in addition to the common OAuth 2.0 properties.

Show script properties
accessToken

The access token to be updated.

identity

Contains a representation of the identity of the resource owner.

Scope validator plugin

Use this plugin to configure the OAuth2 provider to validate the set of requested scopes against the allowed scopes and, optionally, to modify the list of valid scopes.

The plugin comprises four functions that let you customize the validation of scopes at the following endpoints:

Function / Method Endpoint

validateAuthorizationScope

/authorize

validateAccessTokenScope

/authorize and /access_token

validateRefreshTokenScope

/refresh

validateBackChannelAuthorizationScope

/bc_authorize

To view a sample script, including the available script properties, see oauth2-validate-scope.js

Example scope validator plugin

Complete the following steps to implement a scope validator script that modifies the list of valid scopes.

Prepare the scope validator script

This task decribes how to create a script to add an extra scope value.

  1. In the AM admin UI, go to Realms > Realm Name > Scripts, and click New Script.

  2. Enter a unique name for your script, select OAuth2 Validate Scope from the Script Type drop-down list, and click Create.

  3. Copy the oauth2-validate-scope.js script and paste in the Script field.

    • Update the script by inserting the following line of code preceding return scopes; on line 69:

       scopes.add("customscope");
  4. Save your changes.

The scope validator script is now amended to add customscope to the requested scopes.

Configure AM to use the custom scope validator script

Perform this task to set up the OAuth2 provider to use the scope validator script.

  1. Log in to the AM admin UI as an administrator.

  2. Configure the OAuth2 Provider:

    • If no provider exists for the current realm, create a new OAuth 2.0 provider:

      1. Go to Realms > Realm Name > Services and click Add a Service.

      2. Select OAuth2 Provider service from the drop-down list, leave the fields unchanged, and click Create.

    • Otherwise, go to Realms > Realm Name > Services > OAuth2 Provider.

      The OAuth2 provider configuration is displayed.

      For information on OAuth 2.0 provider properties, see OAuth2 Provider.

  3. Select the Plugins tab to edit the following settings:

    1. Set Scope Validator Plugin Type to SCRIPTED.

    2. Set Scope Validator Script to the name of the script you created.

  4. Save your changes.

Create an OAuth2 client

Create an OAuth 2.0 client to use in the client credentials grant flow.

  1. In the AM console, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.

  2. Enter the following values:

    • Client ID: myClient

    • Client secret: forgerock

    • Redirection URIs: https://www.example.com:443/callback

    • Scope(s): access

  3. In Advanced > Grant Types, add Client Credentials.

  4. Click Create.

  5. Save your changes.

AM is now configured for you to try the sample scope validator script.

Try the custom scope validator plugin script

To try your custom script, use the Client credentials grant flow.

  1. Send a POST request to the /oauth2/access_token endpoint, specifying the grant type as client_credentials, scope as access, and your client details.

    For example:

    $ curl \
    --request POST \
    --data "grant_type=client_credentials" \
    --data "client_id=myClient" \
    --data "client_secret=forgerock" \
    --data "scope=access" \
    "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/access_token"
    {
      "access_token": "M3M2Jb2SMjvgWhzNas2SVy2LALg",
      "scope": "access",
      "token_type": "Bearer",
      "expires_in": 3599
    }
  2. Call the /oauth2/tokeninfo (Legacy) endpoint to inspect the custom scope values. Include the access token value obtained in the previous request.

    For example:

    $ curl \
    "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/tokeninfo\
    ?access_token=M3M2Jb2SMjvgWhzNas2SVy2LALg"
    {
      "access_token": "M3M2Jb2SMjvgWhzNas2SVy2LALg",
      "access": "",
      "grant_type": "client_credentials",
      "auditTrackingId": "f9a8395d-1bac-4cba-8b09-8cc336dc49e2-6810",
      "scope": ["access", "customscope"],
      "realm": "/alpha",
      "token_type": "Bearer",
      "expires_in": 3583,
      "authGrantId": "l3355H89FDSWsfdKJmvWssGk_oE",
      "customscope": "",
      "client_id": "myClient"
    }

    Verify that the response contains both the requested scope and the additional scope, customscope.

OAuth 2.0 scope validator scripting API

The following properties are available to scope validator scripts, in addition to the common OAuth 2.0 properties.

Show script properties
requestedScopes

The set of requested scopes.

defaultScopes

The set of default scopes.

allowedScopes

The set of allowed scopes.

User info claims plugin

This plugin extension point is invoked when issuing an ID token or during a request to the /userinfo OpenID Connect endpoint. Use this script to retrieve claim values based on an issued access token.

To view a sample script, including the available script properties, see oidc-claims-extension.js.

Example user info claims plugin

Complete the following steps to implement an example user info claims script that adds a custom claim to the profile scope:

Prepare the user info claims script

This task describes how to create a script to map a custom claim.

  1. In the AM admin UI, go to Realms > Realm Name > Scripts, and click New Script.

  2. Enter a unique name for your script, select OIDC Claims Script from the Script Type drop-down list, and click Create.

  3. Copy the oidc-claims-extension.js script and paste in the Script field.

  4. In the Script field:

    • As a simple example, insert a new claim, myTestName, in the profile (around line 127):

      utils.setScopeClaimsMap({
              profile: [
                  'name',
                  'myTestName',
                  'family_name',
                  'given_name',
                  'zoneinfo',
                  'locale'
              ],
              email: ['email'],
              address: ['address'],
              phone: ['phone_number']
          });
    • Add a value for myTestName around line 199, as follows:

      utils.setClaimResolvers({
      
         name: utils.getUserProfileClaimResolver('cn'),
         myTestName: utils.getUserProfileClaimResolver('cn'),
         family_name: utils.getUserProfileClaimResolver('sn'),
         ...
      });

    For a more complex example of customizing the user info claims script, see How do I add a session property claim to the OIDC Claims Script in the Knowledge Base.

    You can also use the script to override the claims included in an ID token. For details, see How do I override claims in the OIDC ID token in Identity Cloud or AM 7.1.x?

  5. Save your changes.

The default user info claims script is now amended to retrieve a custom claim for the profile scope.

Configure AM to use the user info claims script

Perform this task to set up an OAuth2 provider to use your custom script.

  1. Log in to the AM admin UI as an administrator.

  2. Configure the OAuth2 Provider:

    • If no provider exists for the current realm, create a new OAuth 2.0 provider:

      1. Go to Realms > Realm Name > Services and click Add a Service.

      2. Select OAuth2 Provider service from the drop-down list, leave the fields unchanged, and click Create.

    • Otherwise, go to Realms > Realm Name > Services > OAuth2 Provider.

      The OAuth2 provider configuration is displayed.

      For information on OAuth 2.0 provider properties, see OAuth2 Provider.

      By default, a new OAuth 2.0 provider uses the template user info claims script.

  3. For existing providers, select the Plugins tab to ensure the following settings are configured correctly:

    1. Set OIDC Claims Plugin Type to SCRIPTED.

    2. Set OIDC Script to the name of the script you created.

  4. Save your changes.

Create an OAuth2 client for authorization

Create a public OAuth 2.0 client to use in the authorization request.

  1. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.

  2. Enter the following values:

    • Client ID: myClient

    • Client secret: forgerock

    • Redirection URIs: https://www.example.com:443/callback

    • Scope(s): openid profile

  3. Click Create.

  4. In the Core tab, set Client type to Public.

  5. In the Advanced tab, set the following values:

    • Grant Types: Implicit

    • Token Endpoint Authentication Method: none

    • Response Types: token id_token

AM is now prepared for you to try the sample user info claims script.

Try the custom user info claims plugin script

To try your custom script, use the Implicit grant flow as demonstrated in the following steps.

  1. Log in to AM as the demo user, for example:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://<tenant-name>.forgeblocks.com/am/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }

    Note the SSO token value returned as tokenId in the output.

  2. Invoke the authorization server’s /oauth2/authorize endpoint specifying the SSO token value in a cookie, and the following parameters as a minimum:

    • client_id=myClient

    • response_type=token id_token

    • scope=openid profile

    • nonce=your nonce value

    • redirect_uri=https://www.example.com:443/callback

    • decision=allow

    • csrf=SSO-token

      For example:

      $ curl --dump-header - \
      --Cookie "<session-cookie-name>=AQIC5wM…​TU3OQ*" \
      --request POST \
      --data "client_id=myClient" \
      --data "response_type=token id_token" \
      --data "scope=openid profile" \
      --data "state=123abc" \
      --data "nonce=abc123" \
      --data "decision=allow" \
      --data "csrf=AQIC5wM…​TU3OQ*" \
      --data "redirect_uri=https://www.example.com:443/callback" \
      "https://<tenant-name>.forgeblocks.com/am/oauth2/realms/root/realms/alpha/authorize"

      If the authorization server successfully authenticates the user, note the value of the access token appended to the redirection URI in the response.

  3. Call the /oauth2/userinfo endpoint to inspect the custom claim values, including the access token obtained from the previous request.

    For example:

    $ curl --request GET --header "Authorization: Bearer az91IvnIQ-uP3Eqw5QqaXXY_DCo" \
    "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/userinfo"
    {
      "given_name":"Demo First Name",
      "family_name":"Demo Last Name",
      "name":"demo",
      "myTestName":"demo",
      "sub":"(usr!demo)",
      "subname":"demo"
    }

    Verify that the response contains the custom claim added by the script (myTestName in this example).

OAuth 2.0 user info claims scripting API

The following properties are available to user info claims scripts, in addition to the common OAuth 2.0 script properties.

Show script properties
claims

Contains a map of the claims the server provides by default. For example:

{
  "sub": "248289761001",
  "updated_at": "1450368765"
}
claimsLocales

The values from the 'claims_locales' parameter. For details, see Claims Languages and Scripts in the OpenID Connect Core 1.0 specification..

claimObjects

The default claims provided by the server. Always present.

clientProperties

A map of properties configured in the relevant client profile. Only present if the client was correctly identified.

The keys in the map are as follows:

clientId

The URI of the client.

allowedGrantTypes

The list of the allowed grant types (org.forgerock.oauth2.core.GrantType) for the client.

allowedResponseTypes

The list of the allowed response types for the client.

allowedScopes

The list of the allowed scopes for the client.

customProperties

A map of any custom properties added to the client.

Lists or maps are included as sub-maps. For example, a custom property of customMap[Key1]=Value1 is returned as customMap > Key1 > Value1.

To add custom properties to a client, go to OAuth 2.0 > Clients > Client ID > Advanced, and update the Custom Properties field. The custom properties can be added in the format shown in these examples:

customproperty=custom-value1
customList[0]=customList-value-0
customList[1]=customList-value-1
customMap[key1]=customMap-value-1
customMap[key2]=customMap-value-2

From within the script, you can then access the custom properties in the following way:

var customProperties = clientProperties.get("customProperties");
var property = customProperties.get(<PROPERTY_KEY>);
identity

Contains a representation of the identity of the resource owner.

requestedClaims

Contains requested claims if the claims query parameter is used in the request, and if Enable "claims_parameter_supported" is checked in the OAuth 2.0 provider service configuration; otherwise, this property is empty.

For more information see Requesting Claims using the "claims" Request Parameter in the OpenID Connect Core 1.0 specification.

Example:

{
  "given_name": {
    "essential": true,
    "values": [
      "Demo User",
      "D User"
    ]
  },
  "nickname": null,
  "email": {
    "essential": true
  }
}
requestedTypedClaims

Contains a list of requested claims if the claims query parameter is used in the request, and Enable "claims_parameter_supported" is checked in the OAuth 2.0 provider service configuration. Otherwise, this property is empty.

A claim with a single value indicates this is the only value that should be returned.

requestProperties

A map of the properties present in the request. Always present.

The keys in the map are as follows:

requestUri

The URI of the request.

realm

The realm to which the request was made.

requestParams

The request parameters, and/or posted data. Each value in this map is a list of one, or more, properties.

To mitigate the risk of reflection-type attacks, use OWASP best practices when handling these properties. For example, see Unsafe use of Reflection.

scopes

Contains a set of the requested scopes. For example:

[
  "profile",
  "openid"
]
session

Contains a representation of the user’s session object if the request contained a session cookie.

Copyright © 2010-2022 ForgeRock, all rights reserved.