OpenID Connect 1.0
These pages cover concepts, configuration, and usage procedures for working with OpenID Connect 1.0 (OIDC) and ForgeRock Access Management.
Configuration
Configure the OAuth 2.0 authorization server to act as an OpenID provider.
Dynamic client registration
Discover how clients can register and manage their information dynamically.
OpenID Connect flows
Discover the OIDC flows and how to implement them.
Authentication requirements
Set requirements for authentication during OIDC flows.
Scopes and claims
Learn about OIDC claims and how to request them.
OpenID Connect endpoints
Endpoints exposed when AM acts as an OpenID Provider.
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 OpenID provider
An OAuth 2.0 authentication server that implements OpenID Connect (OIDC) is referred to as an OpenID provider (OP). An OAuth 2.0 client that uses OIDC is also referred to as a relying party (RP).
In its role as an OP, AM returns ID tokens to relying parties. Because OIDC extends OAuth 2.0, when AM is configured as an OP it can also return access and refresh tokens to relying parties.
Before configuring OIDC in your environment, ensure you are familiar with the OAuth 2.0 standards and the AM implementation of OAuth 2.0. |
OIDC concepts
OIDC is an identity layer built on top of OAuth 2.0. It lets clients verify the identity of a user based on the authentication performed by OAuth 2.0 authorization servers. It also lets clients obtain profile information about the user over REST.
The following sequence diagram demonstrates the basic OIDC flow:
OIDC clients can register with the OP and manage their client data dynamically.
To let clients discover an end user’s OP, its endpoints and how to interact with it, AM supports the OpenID Connect Discovery 1.0 specification.
OAuth 2.0 or OIDC?
The OAuth 2.0 and OIDC standards were both created for users who need to interact with a third party service; however, they aim to solve different problems. This topic compares OAuth 2.0 and OIDC functionality and the actors in the implementation of both standards.
OAuth 2.0 | OIDC | |
---|---|---|
Purpose |
Gives users a way to authorize a service to access and use a subset of their data on their behalf in a secure way. Users must agree to provide access under the service’s terms and conditions; for example, how long the service has access to their data and what the data is used for. |
Gives users a way to authenticate to a service by providing it with a subset of their data in a secure way. Because OIDC extends OAuth 2.0, users can authorize a relying party to collect a subset of their data (usually information stored in the user’s profile) from a third party. The service then uses this data to authenticate the user and provide its services. The user can therefore use the relying party’s services even if they have never created an account with the relying party. |
Use cases |
Use cases are generic and can be tailored to many needs. A common example is a user allowing a photo print service access to a third-party server hosting their pictures, so the photo print service can print them. |
The most common scenario is using social media credentials to log in to a third-party service provider. |
Tokens |
Access and refresh tokens |
ID tokens |
Role of scopes |
Scopes limit the information that can be shared with the service or what the service can do with the data.
For example, the OAuth 2.0 scopes are not data and are not related to user data in any way. |
Scopes can be mapped to specific user data.
For example, AM maps the Claims are returned as part of the ID token.
In some cases, additional claims can be requested in a call to the For more information about how AM maps user profile attributes to claims, see Claims. |
OIDC actor | OAuth 2.0 actor | Description |
---|---|---|
End user |
Resource owner (RO) |
The owner of the information the application needs to access. The end user who wants to use an application through an existing identity provider account, without signing up to and creating credentials for yet another web service. |
Relying party (RP) |
Client |
The third-party that needs to know the identity of the end user to provide their services. For example, a delivery company or a shopping site. |
OpenID provider (OP) |
Authorization server (AS) Resource server (RS) |
A service that has the end user’s consent to provide the RP with access to some of its user information. OIDC defines unique identification for an account (subject identifier + issuer identifier). The RP can use this identification as a key to the user profile. In the case of an online mail application, the key could be used to access the user’s mailboxes and related account information. In the case of an online shopping site, the key could be used to access personalized offerings, account, shopping cart, and so on. The key makes it possible to serve users as if they had local accounts. AM can act as the OP to authenticate end users and provide RPs with information about the users in the form of an OIDC token. |
AM and OIDC
This section describes AM’s implementation of OIDC, including the supported grant types and standards.
Grant types
-
Authorization code
-
Authorization code with PKCE
-
Backchannel request
-
Implicit
-
Hybrid
-
Hybrid with PKCE
For details, refer to OpenID Connect grant flows.
Standards
This section lists the OIDC standards that AM supports. For more information, refer to the complete list of supported OIDC and OAuth 2.0 standards.
Session management and logout
Relying parties can:
-
Track whether end users are logged in at the provider using an invisible iframe and the HTML 5 postMessage API.
-
Initiate end user logout at the provider using an endpoint.
AM can also send logout tokens to relying parties when end user sessions linked to ID tokens become invalid. For more information, see OIDC user sessions.
Discovery and dynamic client registration
OIDC defines how a relying party can discover the OP and the corresponding OIDC configuration for an end user. The discovery mechanism relies on WebFinger to get the information, based on the end user’s identifier. The server returns the information in JSON Resource Descriptor (JRD) format.
For details, refer to OIDC discovery and Dynamic client registration.
Mobile Connect
Mobile Connect extends OIDC to let mobile phones be used as authentication devices. This allows mobile network operators to act as identity providers.
For details, refer to GSMA Mobile Connect.
OIDC discovery
To let relying parties (or clients) discover the OP for an end user, AM supports the OpenID Connect Discovery 1.0 specification. In addition to discovering the OP for an end user, the relying party can request the OP configuration.
AM exposes the following REST endpoints for discovering the URL of the OP and its configuration:
Discovery relies on the WebFinger protocol to
discover information about people and other entities, using standard HTTP methods.
WebFinger uses Well-Known URIs,
which defines the path prefix /.well-known/
for the URLs defined by OIDC discovery.
Relying parties need to find the right host:port/deployment-uri combination to locate the well-known endpoints.
You must manage the redirection to AM using your proxies, load balancers, and others,
such that a request to http://www.example.com/.well-known/webfinger
reaches,
for example, https://openam.example.com:8443/openam/.well-known/webfinger
.
When the relying party has discovered the URL of the OP, it can register with the OP dynamically. For test purposes, or if it suits your environment better, you can also register clients manually.
The /.well-known/webfinger
endpoint is disabled by default. To enable it, follow these steps:
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > OpenID Connect.
-
Enable OIDC Provider Discovery.
-
Save your changes.
The discovery endpoint now allows searches for users within this realm only. Repeat these steps in other realms, as required.
Security considerations
AM provides the following security mechanisms to ensure that OIDC ID tokens are properly protected against malicious attackers:
-
TLS
-
Digital signatures
-
Token encryption
When you are designing a security mechanism, take into account the points developed in the section on Security considerations in the OpenID Connect Core 1.0 incorporating errata set 1 specification.
OIDC requires that network messages are protected with Transport Layer Security (TLS).
For information about protecting traffic to and from the web container in which AM runs, refer to Secrets, certificates, and keys.
For additional information, refer to the OAuth 2.0 Security considerations.
Token storage location
OIDC and OAuth 2.0-related services are stateless in AM, unless otherwise indicated; they do not hold any token information locally.
Access and refresh tokens can be stored in the CTS token store or presented to clients as JWTs; however, OIDC tokens and session information are managed in the following way:
-
ID tokens are always presented as JWTs.
-
OIDC sessions are always stored in the CTS token store.
For more information about how to configure access and refresh token storage, refer to Token storage location.
OpenID provider configuration
You can configure the AM OAuth 2.0 provider service to act as an OpenID provider (OP).
To do so, configure the OAuth 2.0 provider service then refer to OIDC-specific configuration.
OIDC-specific configuration
-
To set the OAuth 2.0 provider configuration in the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider.
-
To adjust global defaults, in the AM admin UI, go to Configure > Global Services > OAuth2 Provider.
See the OAuth2 provider reference section for details on each configuration property.
Task | Resources | ||
---|---|---|---|
Configure the public keys for the provider OPs sign ID tokens so that clients can ensure their authenticity. AM exposes the URI where clients can check the signing public keys to verify the ID token signatures. By default, AM exposes an endpoint with keys, but you can configure the URI of your secrets API instead. |
|||
Enable the OpenID Connect Discovery endpoint The discovery endpoint is disabled by default when you configure the OAuth 2.0 provider service. Enable the endpoint if your clients need to discover the URL of the provider for a given user. |
|||
Configure pairwise subject types for dynamic registration To provide different values to the Also, change the default value of the Subject Identifier Hash Salt field on the same tab.
|
N/A |
||
Specify whether AM should return scope-derived claims in the ID token Scope-derived claims, such as those returned when requesting the |
|||
Configure how AM maps scopes to claims and user profile attributes Use scripts to map different user profile attributes to claims and scopes. |
|||
Configure the OP for dynamic client registration and management AM supports several methods of dynamic client registration. You can also register the clients manually. |
|||
Add authentication requirements to ID tokens Require end users to satisfy specific authentication rules or conditions when authenticating to the OP, such as using a specific authentication tree. |
|||
Configure AM for GSMA Mobile Connect Configure the OAuth 2.0 authorization server to act as a Mobile Connect provider. |
|||
Configure the secret AM uses to sign ID tokens and logout tokens ID tokens and backchannel logout tokens are always signed. By default, AM uses a test secret to sign them; change it in production environments. |
|||
Configure the OP to encrypt ID tokens and logout tokens By default, ID tokens and backchannel logout tokens are signed. If these tokens carry sensitive information about your end users, consider encrypting them. |
|||
Configure the methods and algorithms available for signed or encrypted JWTs in the If your clients send request parameters to the authorization endpoint as a JWT instead of as HTTP parameters, configure the Request Parameter* fields on the Advanced OpenID Connect tab. Note that the alias mapped to the encryption algorithms are defined in the secret stores. |
Encrypt ID tokens and backchannel logout tokens
AM supports encrypting ID tokens and backchannel logout tokens to protect them against tampering attacks, which is outlined in the JSON Web Encryption specification (RFC 7516).
ID tokens and backchannel logout tokens share the same encryption configuration. You either encrypt both or none.
-
Go to Realms > Realm Name > Applications > OAuth 2.0 > Clients > Client ID.
-
On the Signing and Encryption tab, select Enable ID Token Encryption.
-
In the Id Token Encryption Algorithm field, enter the algorithm AM will use to encrypt ID tokens and backchannel logout tokens:
Supported 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 (not recommended). -
dir
- Direct encryption with AES using the hashed client secret. -
ECDH-ES
- Elliptic Curve Diffie-Hellman -
ECDH-ES+A128KW
- Elliptic Curve Diffie-Hellman + AES Key Wrapping with 128-bit key. -
ECDH-ES+A192KW
- Elliptic Curve Diffie-Hellman + AES Key Wrapping with 192-bit key. -
ECDH-ES+A256KW
- Elliptic Curve Diffie-Hellman + AES Key Wrapping with 256-bit key. -
X25519
- Elliptic Curve Diffie-Hellman with Curve25519. -
X448
- Elliptic Curve Diffie-Hellman with Curve448.
Only the
P-256
,P-384
, andP-521
curves are supported. -
-
In the ID Token Encryption Method field, enter the method AM will use to encrypt ID tokens and backchannel logout tokens:
Supported encryption methods
-
A128CBC-HS256
- AES 128-bit in CBC mode using HMAC-SHA-256-128 hash (HS256 truncated to 128 bits) -
A192CBC-HS384
- AES 192-bit in CBC mode using HMAC-SHA-384-192 hash (HS384 truncated to 192 bits) -
A256CBC-HS512
- AES 256-bit in CBC mode using HMAC-SHA-512-256 hash (HS512 truncated to 256 bits) -
A128GCM
- AES 128-bit in GCM mode -
A192GCM
- AES 192-bit in GCM mode -
A256GCM
- AES 256-bit in GCM mode
-
-
If you selected an RSA encryption algorithm, perform one of the following actions:
-
Enter the public key in the Client ID Token Public Encryption Key field.
-
Enter a JWK set in the Json Web Key field.
-
Enter a URI containing the public key in the Json Web Key URI field.
-
-
If you selected an ECDH-ES encryption algorithm, perform one of the following actions:
-
Enter a JWK set in the Json Web Key field.
-
Enter a URI containing the public key in the Json Web Key URI field.
-
-
If you selected an algorithm different from RSA or ECDH-ES, go to the Core tab and store the private key/secret in the Client Secret field.
Several features of OAuth 2.0 use the string stored in the Client Secret field to sign/encrypt tokens or parameters when you configure specific algorithms. For example, signing ID tokens with HMAC algorithms, encrypting ID tokens with AES or direct algorithms, or encrypting OpenID Connect parameters with AES or direct algorithms.
In this case, these features must share the key/secret stored in the Client Secret field, and you must ensure that they are configured with the same algorithm.
Claims
OpenID Connect relies on claims to provide information about the end user to the relying parties.
What are claims?
A claim is a piece of information about the end user that the relying party or client can use to provide them a service.
Consider a page that lets the end user register using their Google account information instead of providing the information themselves. The page requests Google a set of claims about the end user, and uses the information on the claims to set up the account without user interaction.
If the end user agrees to share access to their claims, OpenID providers can return them in two ways:
either as key pairs in the ID token, or by making them available at the userinfo
endpoint.
Part of implementing OpenID Connect in your environment is deciding which claims are safe to travel in the ID token,
and which ones require the client to access the endpoint.
ID tokens contain additional claims that are not related to user information directly,
but that are relevant to the flow, the relying party, or the authorization server.
These are similar to those contained in access tokens; for example, iss
, aud
, exp
, and others.
Read more:
AM supports Normal Claims, as specified in section 5.6 of the specification. The optional Aggregated Claims and Distributed Claims representations are not supported by AM. |
When AM is configured as an authorization server, a scope is a concept.
For example, Facebook has an OAuth 2.0 scope named read_stream
.
AM returns allowed scopes in the access token, but it does not associate any data with them.
When AM is configured as an OpenID provider, scopes can relate to data in a user profile by making use of one or more claims.
As each claim represents a piece of information from the user profile, AM displays the actual data the relying party will receive if the end user consents to sharing it:
AM maps scopes and profile data to claims using a script configured in the OAuth2 provider service.
By default, the script maps several user profile attributes to the profile
scope:
Claim | User profile attribute |
---|---|
|
|
|
|
|
|
|
|
|
|
After a successful flow, the OpenID provider returns an ID token with the relevant claims. However, for security reasons, AM does not return scope-derived claims in the ID token by default.
Request claims in ID tokens
Sometimes you may need the provider to return scope-derived claims in the ID token. For example, when claims are related to authentication conditions or rules the end user needs to satisfy before being redirected to particular resources.
You can configure AM to either return all scope-derived claims in the ID token, or just the ones specified in the request:
-
To configure the provider to always return scope-derived claims in the ID token, enable Always Return Claims in ID Tokens (Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect).
This option is disabled by default because of the security concerns of returning claims that may contain sensitive user information.
-
To request that the provider only include certain scope-derived claims in the ID token, enable the property Enable "claims_parameter_supported" (Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect) and request said claims in the
claims
parameter.
Voluntary and essential claims in the claims parameter
Claims specified using the claims
parameter can be voluntary or essential:
-
Essential. The relying party specifies a number of claims that are necessary to ensure a good experience to the end user.
For example, to provide personalized services, the relying party may require the end user’s phone number to send them an SMS.
-
Voluntary. The relying party specifies a number of claims that are useful but not required to provide services to the end user.
For an example on requesting voluntary and essential claims, refer to Demonstrate authentication requirements.
Clients can still retrieve additional claims from the /oauth2/userinfo
endpoint.
The OAuth 2.0 provider’s Supported Claims field restricts the claims that can be granted in ID tokens, but not the claims a client can register with during dynamic client registration. You can also use this field to configure how AM presents the claims in the AM consent screen. By default, scope-derived claims are not configured to display in the consent screen. You can either configure clients to use implied consent, or manually configure the claims to display. How to configure claims in the AM consent screenConfigure how claims appear in the consent screen by client or by realm (in the OAuth 2.0 provider service). For examples, see the Supported Claims field in the provider’s Advanced reference, or the Claim(s) field in Core properties. Claims may be entered as simple strings or pipe-separated strings
representing the internal claim name, locale, and localized description.
For example: If the description is omitted, the claim is not displayed in the consent page. This may be useful when the client requires claims that are not meaningful for the end user. Client-level configuration overrides that at provider level. |
Customize claims with the OpenID Connect 1.0 claims script
The OIDC Claims
script is part of the user info claims plugin, one of the OAuth 2.0 plugin
extension points provided by AM. Use this extension point when issuing an ID token or
during a request to the /userinfo
OpenID Connect endpoint.
To configure a different script of the type OIDC Claims
,
go to Realms > Realm Name > Services > OAuth 2.0 Provider > Plugins,
and select it in the OIDC Claims Script drop-down menu.
Alternatively, to configure a different script as the default for all new OAuth2 providers, update the setting in Configure > Global Services > OAuth2 Provider > Plugins.
To examine the contents of the default OIDC claims script and to view the available script properties, go to Realms > Realm Name > Scripts, and select the OIDC Claims Script.
For information about how to configure OAuth 2.0 plugins, see Customize OAuth 2.0. For details about the user info claims plugin, see OIDC user info claims. |
Dynamic client registration
AM supports dynamic registration. RFC 7591 OAuth 2.0 Dynamic Client Registration Protocol and OpenID Connect (OIDC) Dynamic Client Registration 1.0 describe the dynamic registration options for OAuth 2.0 and OIDC client applications.
AM returns an error when a dynamic client registration request payload includes incorrect information or specifies unsupported signing and encryption algorithms. For example, if a public client requests symmetric signing or encryption, the request results in an error because public clients cannot have a client secret to use for symmetric encryption.
Dynamic registration options
- Open registration
-
The application registers its profile without an access token.
AM generates
client_id
andclient_secret
values. AM ignores any values provided in the profile for these properties.You can use this method to develop and test client registration. This method does not limit the number of client registrations. If you use it in production, also require a software statement.
- Registration with mutual TLS authentication
-
The application provides a self-signed or a CA-signed X.509 certificate for authentication, as defined in the Internet-Draft OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens.
- Registration with an access token
-
The application registers its profile with an access token for authorization.
The specification does not describe how the client obtains the access token. In AM, you register an initial OAuth 2.0 client application manually, and use this application to obtain the access token on behalf of the client requesting registration.
To register the
logo_uri
,client_uri
, andpolicy_uri
the access token must include a special scope; default:dynamic_client_registration
. - Registration with a software statement
-
The application registers its profile with a software statement.
A software statement is a JSON Web Token (JWT) that holds registration claims about the client, such as its issuer and redirection URIs.
A software statement is issued by a software publisher. The software publisher encrypts and signs the claims in the software statement.
You store software publisher details in a software publisher profile. The software publisher profile identifies the issuer included in software statements. It provides access to the secret or the keys to decrypt software statement JWTs and to verify their signatures. When the client registers dynamically with a software statement, AM uses the software publisher profile to determine whether it can trust the software statement.
The protocol specification does not describe how the client obtains the software statement JWT. AM expects the software publisher to construct the JWT according to the settings in its profile.
Enable dynamic client registration
Option | Create or update… |
---|---|
Open registration |
|
Registration with a certificate |
|
Registration with an access token |
|
Registration requires a software statement JWT |
OAuth 2.0 provider settings
To enable open registration and registration with a software statement, update the OAuth 2.0 provider configuration for the realm:
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider and switch to the Client Dynamic Registration tab.
-
To allow open registration without an access token, enable Allow Open Dynamic Client Registration.
-
To require a software statement to register, enable Require Software Statement for Dynamic Client Registration, and edit the Required Software Statement Attested Attributes list to include all the required claims.
-
Save your work.
-
To change the scopes a client can register, switch to the Advanced tab and update the Client Registration Scope Allowlist field.
-
Save your work.
For additional details, refer to the Client dynamic registration reference.
Client profile for access tokens
To enable dynamic registration with an access token, manually register a service application to provide the access tokens:
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients and click + Add Client.
-
Provide the client application details; for example:
- Client ID
-
registration-service
- Client Secret
-
forgerock
- Scopes
-
dynamic_client_registration
If the string for the special scope is not the default, use the scope specified in the OAuth 2.0 provider configuration Client Dynamic Registration > Scope to give access to dynamic client registration field.
-
Save your work.
Software publisher profile
To enable dynamic registration with a software statement JWT, register a software publisher:
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Software Publisher and click Add Software Publisher Agent.
-
Add the basic settings as necessary before you click Create:
- Agent ID
-
Required identifier for the profile.
- Software publisher secret
-
Secret required when the publisher uses HMAC symmetric encryption for the JWTs.
- Software publisher issuer
-
Required issuer identifier to match the
iss
claim in JWTs.
-
Configure the appropriate security settings:
-
If you provide the JSON Web Key (JWK) by URI rather than by value, where the Public key selector is
JWKs_URI
, AM must access the JWKs when processing registration requests. -
If the publisher uses symmetric encryption, where the Software statement signing Algorithm is
HS256
,HS384
, orHS512
, the Software publisher secret must match thek
value in the JWK.
-
-
Save your work.
The software publisher provides client applications using dynamic registration with a valid software statement JWT. Valid software statement JWTs must have:
-
All the required claims listed in the OAuth 2.0 provider’s Required Software Statement Attested Attributes.
-
An issuer (
iss
) claim matching a publisher profile’s Software publisher issuer.
These constraints apply to software statement JWTs:
-
Compressed JWTs must not be larger than 32 KiB (32768 bytes) when uncompressed.
-
AM ignores keys specified in JWT headers, such as
jku
andjwe
.
Registration examples
Review the following dynamic client registration examples.
The client must read and store the dynamic registration response. The response includes important information about the client, such as:
-
The generated client ID and the generated client secret for confidential clients.
You cannot choose the client ID or client secret when registering an application dynamically.
-
The URL and access token required to update the client profile.
Open registration
The following example depends on an update to OAuth 2.0 provider settings. When you have enabled Allow Open Dynamic Client Registration, register a client dynamically.
Include a client_name
in the payload as the human-readable name to display to resource owners:
$ curl \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"redirect_uris": ["https://client.example.com/callback"],
"client_name#en": "My Client",
"client_name#ja-Jpan-JP": "\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
"client_uri": "https://client.example.com/"
}' \
'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register'
Show the response
{
"authorization_signed_response_alg": "RS256",
"request_object_encryption_alg": "",
"introspection_encrypted_response_alg": "RSA-OAEP-256",
"client_uri": "https://client.example.com/",
"default_max_age": 1,
"application_type": "web",
"introspection_encrypted_response_enc": "A128CBC-HS256",
"introspection_signed_response_alg": "RS256",
"client_name#en": "My Client",
"userinfo_encrypted_response_enc": "",
"registration_client_uri": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register?client_id=<generated-client-id>",
"client_type": "Confidential",
"userinfo_encrypted_response_alg": "",
"registration_access_token": "<generated-registration-access-token>",
"client_id": "<generated-client-id>",
"token_endpoint_auth_method": "client_secret_basic",
"userinfo_signed_response_alg": "",
"public_key_selector": "x509",
"scope": "address phone openid profile email",
"require_pushed_authorization_requests": false,
"authorization_code_lifetime": 0,
"client_secret": "<generated-client-secret>",
"user_info_response_format_selector": "JSON",
"tls_client_certificate_bound_access_tokens": false,
"backchannel_logout_session_required": false,
"id_token_signed_response_alg": "RS256",
"default_max_age_enabled": false,
"token_intro_response_format_selector": "JSON",
"subject_type": "public",
"grant_types": ["authorization_code"],
"jwt_token_lifetime": 0,
"id_token_encryption_enabled": false,
"redirect_uris": ["https://client.example.com/callback"],
"jwks_cache_miss_cache_time": 60000,
"jwks_cache_timeout": 3600000,
"client_name#ja-jpan-jp": "クライアント名",
"id_token_encrypted_response_alg": "RSA-OAEP-256",
"id_token_encrypted_response_enc": "A128CBC-HS256",
"client_secret_expires_at": 0,
"access_token_lifetime": 0,
"refresh_token_lifetime": 0,
"scopes": ["address", "phone", "openid", "profile", "email"],
"request_object_signing_alg": "",
"response_types": ["code"]
}
OIDC clients must include these claims in the JSON registration data:
-
The
openid
scope; for example,"scopes": ["profile", "openid"]
. -
The
id_token
response type; for example,"response_types": ["code", "id_token code"]
.
Registration with mutual TLS authentication
The following example shows the use of mutual TLS (mTLS) for authentication. The configuration depends on the type of certificate:
- CA-signed X.509 certificates (PKI)
-
If applications use CA-signed certificates, configure AM to trust the certificate authorities. For details, refer to Mutual TLS using public key infrastructure.
On registration, the client includes the following properties in its profile data:
-
"token_endpoint_auth_method": "tls_client_auth"
. -
"tls_client_auth_subject_dn": "<certificate-subject-DN>"
; for example,"tls_client_auth_subject_dn": "CN=myOAuth2Client"
.
-
- Self-signed X.509 certificates
-
If applications use self-signed certificates, they can provide their certificates as:
-
A JSON Web Key Set (JWKS).
On registration, the client includes the following properties in its profile data:
-
"token_endpoint_auth_method": "self_signed_tls_client_auth"
. -
The JWKS containing the certificate and prepared according to RFC 7517.
-
-
A JWKS URI, which AM reads to retrieve the certificate.
On registration, the client includes the following properties in its profile data:
-
"token_endpoint_auth_method": "self_signed_tls_client_auth"
. -
"jwks_uri": "<uri>"
; for example,"jwks_uri": "https://www.example.com/mysecureapps/certs"
.
-
-
A single X.509 certificate in PEM format.
On registration, the client includes the following properties in its profile data:
-
"token_endpoint_auth_method": "self_signed_tls_client_auth"
. -
"tls_client_auth_x509_cert": "<pem-format-cert>"
.The
<pem-format-cert>
can omit the-----BEGIN CERTIFICATE-----
and-----END CERTIFICATE-----
labels.
-
-
The following example shows dynamic registration with a self-signed ECDSA P-256 certificate in a JWKS:
Show the example
$ curl \
--request POST \
--header "Content-Type: application/json" \
--data '{
"jwks": {
"keys": [{
"kty": "EC",
"crv": "P-256",
"x": "9BmRru-6AYQ8U_9tUFhMGVG-BvC4vRthzLJTntfSdBA",
"y": "MqPzVSeVNzzgcR-zZeLGog3GJ4d-doRE9eiGkCKrB48",
"kid": "a4:68:90:1c:f6:c1:43:c0",
"x5c": [
"MIIBZTCCAQugAwIB…..xgASSpAQC83FVBawjmbv6k4CN95G8zHsA=="
]
}]
},
"client_type": "Confidential",
"grant_types": ["authorization_code", "client_credentials"],
"response_types": ["code", "token"],
"redirect_uris": ["https://client.example.com:8443/callback"],
"token_endpoint_auth_method": "self_signed_tls_client_auth",
"tls_client_auth_subject_dn": "CN=myOauth2Client",
"tls_client_certificate_bound_access_tokens": true
}' \
"https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register"
{
"request_object_encryption_alg": "",
"default_max_age": 1,
"jwks": {
"keys": [
{
"kty": "EC",
"crv": "P-256",
"x": "9BmRru-6AYQ8U_9tUFhMGVG-BvC4vRthzLJTntfSdBA",
"y": "MqPzVSeVNzzgcR-zZeLGog3GJ4d-doRE9eiGkCKrB48",
"kid": "a4:68:90:1c:f6:c1:43:c0",
"x5c": [
"MIIBZTCCAQugAwIB…..xgASSpAQC83FVBawjmbv6k4CN95G8zHsA=="
]
}
]
},
"application_type": "web",
"tls_client_auth_subject_dn": "CN=myOauth2Client",
"registration_client_uri": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register?client_id=83635999-2794-4fcd-b6b3-67e2d86c1952",
"client_type": "Confidential",
"userinfo_encrypted_response_alg": "",
"registration_access_token": "tu4KR0jO3iGn0ubOOY0YCSfyPmk",
"client_id": "83635999-2794-4fcd-b6b3-67e2d86c1952",
"token_endpoint_auth_method": "self_signed_tls_client_auth",
"userinfo_signed_response_alg": "",
"public_key_selector": "jwks",
…
}
The example sets "tls_client_certificate_bound_access_tokens": true
.
This lets the client obtain certificate-bound access tokens.
For details, refer to Certificate-bound proof-of-possession.
Registration with an access token
The following example depends on a Client profile for access tokens.
-
Use the registration service client to get an access token:
$ curl \ --request POST \ --user 'registration-service:forgerock' \ --data 'grant_type=client_credentials' \ --data 'scope=dynamic_client_registration' \ 'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/access_token' { "access_token": "<access-token>", "scope": "dynamic_client_registration", "token_type": "Bearer", "expires_in": 3596 }
-
Register a client dynamically with the access token as authorization.
Include a
client_name
in the payload as the human-readable name to display to resource owners.$ curl \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <access-token>' \ --data '{ "redirect_uris": ["https://client.example.com/callback"], "client_name#en": "My Client", "client_name#ja-Jpan-JP": "\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D", "client_uri": "https://client.example.com/" }' \ 'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register'
Show the response
{ "request_object_encryption_alg": "", "default_max_age": 1, "application_type": "web", "client_name#en": "My Client", "registration_client_uri": "https://openam.example.com:8443/openam/oauth2/register?client_id=<generated-client-id>", "client_type": "Confidential", "userinfo_encrypted_response_alg": "", "registration_access_token": "<generated-registration-access-token>", "client_id": "<generated-client-id>", "token_endpoint_auth_method": "client_secret_basic", "userinfo_signed_response_alg": "", "public_key_selector": "x509", "authorization_code_lifetime": 0, "client_secret": "<generated-client-secret>", "user_info_response_format_selector": "JSON", "id_token_signed_response_alg": "HS256", "default_max_age_enabled": false, "subject_type": "public", "jwt_token_lifetime": 0, "id_token_encryption_enabled": false, "redirect_uris": ["https://client.example.com/callback"], "client_name#ja-jpan-jp": "クライアント名", "id_token_encrypted_response_alg": "RSA1_5", "id_token_encrypted_response_enc": "A128CBC_HS256", "client_secret_expires_at": 0, "access_token_lifetime": 0, "refresh_token_lifetime": 0, "request_object_signing_alg": "", "response_types": ["code"] }
OIDC clients must include these claims in the JSON registration data:
-
The
openid
scope; for example,"scopes": ["profile", "openid"]
. -
The
id_token
response type; for example,"response_types": ["code", "id_token code"]
.
-
Registration with a software statement
The following example depends on an update to OAuth 2.0 provider settings, a Software publisher profile, and an encrypted software statement JWT:
-
Configure the OAuth 2.0 provider:
This example uses open registration with a software statement. The OAuth 2.0 provider has these settings enabled:
-
Allow Open Dynamic Client Registration
-
Require Software Statement for Dynamic Client Registration
If you leave Allow Open Dynamic Client Registration disabled, use an access token as authorization for the registration request, as demonstrated in Registration with an access token.
-
-
Configure the software publisher account.
The software publisher for this example has the following profile settings:
- Agent ID
-
My Software Publisher
- Software publisher secret
-
secret
- Software publisher issuer
-
https://publisher.example.com
- Software statement signing Algorithm
-
HS256
- Public key selector
-
JWKs
- Json Web Key
-
{"keys":[{"kty":"oct","k":"secret","alg":"HS256"}]}
Notice that the value is a key set rather than a single key.
-
Prepare the software statement.
The plaintext payload of the software statement JWT in this example is the following:
{ "sub": "registrar@example.com", "name": "My Client", "iat": 1675246194, "exp": 1675249794, "iss": "https://publisher.example.com", "redirect_uris": ["https://client.example.com/callback"] }
When you try the example, use current values for the
iat
(issued at) andexp
(expiration time) claims.The JWT header is
{"alg":"HS256","typ":"JWT"}
, and the secret issecret
.The resulting encrypted JWT is as follows with lines folded for readability:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 .eyJzdWIiOiJyZWdpc3RyYXJAZXhhbXBsZS5jb20iLCJuYW1lIjoiSm9obiBE b2UiLCJpYXQiOjE2NzUyNDYxOTQsImV4cCI6MTY3NTI0OTc5NCwiaXNzIjoia HR0cHM6Ly9wdWJsaXNoZXIuZXhhbXBsZS5jb20iLCJyZWRpcmVjdF91cmlzIj pbImh0dHBzOi8vY2xpZW50LmV4YW1wbGUuY29tL2NhbGxiYWNrIl19 .7_3nu39GtTTz_RPKZMjj1JuwWWTgeE4Iqx7p3-cfiPg
-
Register a client dynamically with the software statement JWT:
$ curl \ --request POST \ --header 'Content-Type: application/json' \ --data '{ "redirect_uris": ["https://client.example.com/callback"], "client_name#en": "My Client", "client_name#ja-Jpan-JP": "\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D", "client_uri": "https://client.example.com/", "software_statement": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJyZWdpc3RyYXJAZXhhbXBsZS5jb20iLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE2NzUyNDYxOTQsImV4cCI6MTY3NTI0OTc5NCwiaXNzIjoiaHR0cHM6Ly9wdWJsaXNoZXIuZXhhbXBsZS5jb20iLCJyZWRpcmVjdF91cmlzIjpbImh0dHBzOi8vY2xpZW50LmV4YW1wbGUuY29tL2NhbGxiYWNrIl19.7_3nu39GtTTz_RPKZMjj1JuwWWTgeE4Iqx7p3-cfiPg" }' \ 'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register'
Show the response
{ "authorization_signed_response_alg": "RS256", "request_object_encryption_alg": "", "introspection_encrypted_response_alg": "RSA-OAEP-256", "client_uri": "https://client.example.com/", "default_max_age": 1, "application_type": "web", "introspection_encrypted_response_enc": "A128CBC-HS256", "introspection_signed_response_alg": "RS256", "client_name#en": "My Client", "userinfo_encrypted_response_enc": "", "registration_client_uri": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register?client_id=<generated-client-id>", "client_type": "Confidential", "userinfo_encrypted_response_alg": "", "registration_access_token": "<generated-registration-access-token>", "client_id": "<generated-client-id>", "token_endpoint_auth_method": "client_secret_basic", "userinfo_signed_response_alg": "", "software_statement": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJyZWdpc3RyYXJAZXhhbXBsZS5jb20iLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE2NzUyNDYxOTQsImV4cCI6MTY3NTI0OTc5NCwiaXNzIjoiaHR0cHM6Ly9wdWJsaXNoZXIuZXhhbXBsZS5jb20iLCJyZWRpcmVjdF91cmlzIjpbImh0dHBzOi8vY2xpZW50LmV4YW1wbGUuY29tL2NhbGxiYWNrIl19.7_3nu39GtTTz_RPKZMjj1JuwWWTgeE4Iqx7p3-cfiPg", "public_key_selector": "x509", "scope": "address phone openid profile email", "require_pushed_authorization_requests": false, "authorization_code_lifetime": 0, "client_secret": "<generated-client-secret>", "user_info_response_format_selector": "JSON", "tls_client_certificate_bound_access_tokens": false, "backchannel_logout_session_required": false, "id_token_signed_response_alg": "RS256", "default_max_age_enabled": false, "token_intro_response_format_selector": "JSON", "subject_type": "public", "grant_types": ["authorization_code"], "jwt_token_lifetime": 0, "id_token_encryption_enabled": false, "redirect_uris": ["https://client.example.com/callback"], "jwks_cache_miss_cache_time": 60000, "jwks_cache_timeout": 3600000, "client_name#ja-jpan-jp": "クライアント名", "id_token_encrypted_response_alg": "RSA-OAEP-256", "id_token_encrypted_response_enc": "A128CBC-HS256", "client_secret_expires_at": 0, "access_token_lifetime": 0, "refresh_token_lifetime": 0, "scopes": ["address", "phone", "openid", "profile", "email"], "request_object_signing_alg": "", "response_types": ["code"] }
OIDC clients must include these claims in the JSON registration data:
-
The
openid
scope; for example,"scopes": ["profile", "openid"]
. -
The
id_token
response type; for example,"response_types": ["code", "id_token code"]
.
-
Manage client profiles
The JSON response to a successful dynamic registration request contains the following fields:
registration_client_uri
-
The endpoint for reading and updating the client profile, including the generated client ID as a query parameter.
registration_access_token
-
The generated access token to authorize reading and updating the client profile.
Make sure your client application stores the dynamic registration response, including these values. Your application needs them to read and update its client profile.
Read a client profile
To read a client profile, send an HTTP GET request
to the registration_client_uri
with the registration_access_token
for authorization:
$ curl \
--request GET \
--header 'Authorization: Bearer <generated-registration-access-token>' \
"https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register?client_id=<generated-client-id>"
Show the response
{
"authorization_signed_response_alg": "RS256",
"request_object_encryption_alg": "",
"introspection_encrypted_response_alg": "RSA-OAEP-256",
"client_uri": "https://client.example.com/",
"default_max_age": 1,
"application_type": "web",
"introspection_encrypted_response_enc": "A128CBC-HS256",
"introspection_signed_response_alg": "RS256",
"client_name#en": "My Client",
"userinfo_encrypted_response_enc": "",
"client_type": "Confidential",
"userinfo_encrypted_response_alg": "",
"token_endpoint_auth_method": "client_secret_basic",
"userinfo_signed_response_alg": "",
"client_id": "<generated-client-id>",
"public_key_selector": "x509",
"scope": "openid address phone email profile",
"require_pushed_authorization_requests": false,
"authorization_code_lifetime": 0,
"client_secret": "<generated-client-secret>",
"user_info_response_format_selector": "JSON",
"tls_client_certificate_bound_access_tokens": false,
"backchannel_logout_session_required": false,
"id_token_signed_response_alg": "RS256",
"default_max_age_enabled": false,
"token_intro_response_format_selector": "JSON",
"subject_type": "public",
"grant_types": ["authorization_code"],
"jwt_token_lifetime": 0,
"id_token_encryption_enabled": false,
"redirect_uris": ["https://client.example.com/callback"],
"jwks_cache_miss_cache_time": 60000,
"jwks_cache_timeout": 3600000,
"client_name#ja-jpan-jp": "クライアント名",
"id_token_encrypted_response_alg": "RSA-OAEP-256",
"id_token_encrypted_response_enc": "A128CBC-HS256",
"client_secret_expires_at": 0,
"access_token_lifetime": 0,
"refresh_token_lifetime": 0,
"scopes": ["openid", "address", "phone", "email", "profile"],
"request_object_signing_alg": "",
"response_types": ["code"]
}
The response does not contain the registration_client_uri
or the registration_access_token
.
Update a client profile
When an application updates its client profile rather than registering again dynamically, it retains the current client ID and client secret.
The update request body replaces the current client profile settings subject to these conditions:
-
Updates cannot change any of the following settings:
-
client_id_issued_at
-
client_secret
-
client_secret_expires_at
-
registration_access_token
-
registration_client_uri
-
-
Missing settings are set to their default values.
-
Settings with unrecognized names are silently ignored.
-
If the client profile includes a software statement JWT, it must be valid and current.
-
A successful update returns a new registration access token to use going forward.
To update a client profile, send an HTTP PUT request to the registration_client_uri
with the registration_access_token
for authorization and the request body specifying the new settings.
The following example updates the scope
and grant_types
settings:
$ curl \
--request PUT \
--header 'Authorization: Bearer <generated-registration-access-token>' \
--data '{
"client_name#en": "My Client",
"client_name#ja-jpan-jp": "クライアント名",
"client_id": "<generated-client-id>",
"client_secret": "<generated-client-secret>",
"client_uri": "https://client.example.com/",
"scope": "openid profile",
"grant_types": ["authorization_code", "implicit"],
"redirect_uris": ["https://client.example.com/callback"]
}' \
'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register?client_id=<generated-client-id>'
Show the response
{
"authorization_signed_response_alg": "RS256",
"request_object_encryption_alg": "",
"introspection_encrypted_response_alg": "RSA-OAEP-256",
"client_uri": "https://client.example.com/",
"default_max_age": 1,
"application_type": "web",
"introspection_encrypted_response_enc": "A128CBC-HS256",
"introspection_signed_response_alg": "RS256",
"client_name#en": "My Client",
"userinfo_encrypted_response_enc": "",
"client_type": "Confidential",
"userinfo_encrypted_response_alg": "",
"registration_access_token": "<generated-registration-access-token>",
"client_id": "<generated-client-id>",
"token_endpoint_auth_method": "client_secret_basic",
"userinfo_signed_response_alg": "",
"public_key_selector": "x509",
"scope": "openid profile",
"require_pushed_authorization_requests": false,
"authorization_code_lifetime": 0,
"client_secret": "<generated-client-secret>",
"user_info_response_format_selector": "JSON",
"tls_client_certificate_bound_access_tokens": false,
"backchannel_logout_session_required": false,
"id_token_signed_response_alg": "RS256",
"default_max_age_enabled": false,
"token_intro_response_format_selector": "JSON",
"subject_type": "public",
"grant_types": ["authorization_code", "implicit"],
"jwt_token_lifetime": 0,
"id_token_encryption_enabled": false,
"redirect_uris": ["https://client.example.com/callback"],
"jwks_cache_miss_cache_time": 60000,
"jwks_cache_timeout": 3600000,
"client_name#ja-jpan-jp": "クライアント名",
"id_token_encrypted_response_alg": "RSA-OAEP-256",
"id_token_encrypted_response_enc": "A128CBC-HS256",
"access_token_lifetime": 0,
"refresh_token_lifetime": 0,
"scopes": ["openid", "profile"],
"request_object_signing_alg": "",
"response_types": ["code"]
}
The registration_access_token
in the response reflects the new value to use going forward.
Delete a client profile
To remove a client profile, send an HTTP DELETE request
to the registration_client_uri
with the registration_access_token
for authorization:
$ curl \
--request DELETE \
--header 'Authorization: Bearer <generated-registration-access-token>' \
'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register?client_id=<generated-client-id>'
A successful request returns an HTTP 204 No Content response.
Authorization grants and active tokens associated with the client remain valid until they expire.
OIDC client authentication
OIDC clients use the authentication methods described in OAuth 2.0 client authentication.
OIDC clients must set the authentication method in their profile. In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Advanced and select the method in the Token Endpoint Authentication Method drop-down list:
Method | Description |
---|---|
|
The client sends its credentials in an HTTP Basic |
|
The client sends its credentials as When a client authenticates with form parameters,
the server can store POST data on the user-agent in an |
|
The client is public and does not authenticate. Public clients do not authenticate even if the authentication method is different from |
|
The client sends its credentials as a JSON Web Token (JWT). |
|
The client uses a self-signed certificate for mutual TLS authentication. |
|
The client uses a CA-signed certificate for mutual TLS authentication. |
OpenID Connect grant flows
These pages describe supported OpenID Connect (OIDC) flows and how to implement them.
Decide which flow is best based on the relying party (RP):
RP | Grant | Description |
---|---|---|
The RP is a web application running on a server. |
The OpenID provider (OP) uses the user-agent to transport the authorization code the RP exchanges for tokens. Use the same grant with Proof Key for Code Exchange (PKCE) when possible. |
|
The RP is a native application or a single-page application (SPA); for example, a desktop or mobile application, or a JavaScript application. |
The RP cannot communicate securely with the OP, so the authorization code can be intercepted by malicious users. The PKCE standard mitigates against interception attacks. |
|
The RP knows the end user’s identifier and gains consent through a separate authentication device, such as a mobile phone with an authenticator application. |
The RP does not interact directly with the end user; instead it initiates a backchannel request to the end user’s authentication device to gather consent for the operation. For example, a smart speaker gets consent from its registered end user after receiving a voice request to transfer money to a third party. |
|
The RP is an SPA. |
The OpenID provider (OP) uses the user-agent to transport tokens, exposing them to the end user and other parties. When possible, use the authorization code grant with PKCE instead. |
|
The RP gets an ID token immediately and later gets an access token. |
The OpenID provider (OP) uses the user-agent to transport the authorization code and initial tokens. Use PKCE with this flow when possible. |
Backchannel request grant
Use the backchannel request grant for client-initiated backchannel authentication (CIBA).
CIBA lets a relying party (RP), the consumption device, get an end user’s consent without redirection through the end user’s browser. Instead, the end user authenticates and grants consent through an authentication device such as an authenticator application or a mobile banking application on the user’s mobile phone.
AM applies the guidelines suggested by the OpenID Financial-grade API (FAPI) Working Group to implement CIBA.
The backchannel flow
-
The RP has a user identifier and requires the end user’s consent. It prepares a signed Json Web Token (JWT).
-
The RP sends an HTTP POST request with the signed JWT to AM, the OpenID provider (OP).
-
The OP validates the signature using the RP’s public key and verifies the JWT. If the JWT is valid, the OP returns an
auth_req_id
and a polling interval. -
The RP polls the OP with the
auth_req_id
, waiting for the end user’s authorization. If the RP does not respect the polling interval, the OP returns an error. -
The OP sends a push notification with the
binding_message
to request the end user’s authorization. -
The end user authorizes the request with the authorization gesture on their authentication device; for example, the user clicks a button in their authenticator application or provides their fingerprint.
-
The OP returns an access token and an ID token to the RP.
The RP can use the ID token subject ID claim as the end user’s identity.
-
If the RP requires additional claims, it sends a request to the /oauth2/userinfo endpoint with the access token for authorization.
-
If the access token is valid, the
/oauth2/userinfo
endpoint returns any additional claims.The RP can use the subject ID and the additional claims to identify the end user.
Prepare for CIBA
Configure the service
-
Create a journey such as the following:
The journey uses these nodes:
For details, refer to Push authentication journeys.
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced and make sure the Grant Types field includes
Back Channel Request
.Save any changes you make.
-
Associate the journey with incoming
acr_values
:-
Switch to the Advanced OpenID Connect tab of the OAuth 2.0 provider configuration.
-
In the OpenID Connect acr_values to Auth Chain Mapping box:
-
Set the Key to the value that will be passed in through the
acr_values
claim of the incoming CIBA request. -
Set the Value to the name of your journey.
-
Click Add.
-
-
Save your changes.
For more information, refer to The
acr
claim. -
Register an RP
-
Register the RP as a confidential client application with the following settings:
- Name
-
<human-readable-name>
- Client ID
-
<rp-client-id>
(must match theiss
in the RP’s signed JWTs) - Client Secret
-
<rp-client-secret>
- Scopes
-
openid
profile
-
Configure access to the RP’s public keys so AM can verify JWT signatures:
-
On the Signing and Encryption tab, choose the Public key selector.
-
Depending on the Public key selector value you chose, set one of the other fields appropriately.
-
Save your changes.
For example:
-
Set Public key selector
JWKs_URI
and Json Web Key URI to the URL where the RP publishes its keys.This method simplifies key rotation as AM rereads the keys periodically.
-
Set Public key selector to
JWKs
and set Json Web Key to a JWK set similar to the following:{ "keys": [ { "kty": "EC", "use": "sig", "crv": "P-256", "kid": "myCIBAKey", "x": "m0CkpWpZyGu-FLRLjCGBVGC7Fwm5vGt8Lm3HhYU4ylg", "y": "U8NMtO-C2c3yhu2I_ApAELttmaittfPNPQaIJxvTCHk", "alg": "ES256" } ] }
You can store more than one key in the JWK set.
-
Get an auth request ID
Follow these steps as RP to get a CIBA authentication request ID:
-
Prepare a signed JWT with the required claims in the payload:
Claim Description Example acr_values
A string identifying the mechanism for the end user to provide authorization.
"acr_values": "push"
aud
A string or array of strings indicating the intended audience of the JWT. Must include the authorization server OAuth 2.0 endpoint.
"aud": "https://openam.example.com:8443/openam/oauth2"
binding_message
A short (100 character max.) string message to display to the user when obtaining authorization.
For push notification, messages must:
-
Begin with a letter, number, or punctuation mark.
-
Not include line breaks or control characters.
"binding_message": "Allow ExampleBank to transfer £50 from 'Main' to 'Savings'? (EB-0246326)"
exp
The expiration time in seconds since January 1, 1970 UTC. An expiration time more than 30 minutes in the future causes a
JWT expiration time is unreasonable
error message."exp": 1675681183
id_token_hint
An ID token identifying the principal and subject of the JWT (the end user).
Required when not using
login_hint
."id_token_hint": "<id-token>"
iss
The unique identifier of the JWT issuer; must match the client ID in the application profile.
"iss": "myCIBAClient"
login_hint
A string identifying the principal and subject of the JWT (the end user).
Required when not using
id_token_hint
."login_hint": "a0325ea4-9d9b-4056-931b-ab64704cc3da"
scope
A string holding a space-separated list of the requested scopes; must include
openid
."scope": "openid profile"
For example:
{ "aud": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha", "binding_message": "Allow ExampleBank to transfer £50 from 'Main' to 'Savings'? (EB-0246326)", "acr_values": "push", "exp": 1675681183, "iss": "<rp-client-id>", "login_hint": "<end-user-id>", "scope": "openid profile" }
AM ignores keys specified in JWT headers, such as
jku
andjwe
and uses the keys specified in the RP profile to verify the JWT signature. -
-
Send an HTTP POST to the /oauth2/bc-authorize endpoint with the signed JWT in the payload:
$ curl \ --request POST \ --user '<rp-client-id>:<rp-client-secret>' \ --data 'request=<signed-jwt>' \ 'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/bc-authorize'
AM returns a JSON object with the
auth_req_id
value:{ "auth_req_id": "<auth-req-id>", "expires_in": 600, "interval": 2 }
AM sends a push notification with the
binding_message
to the end user.
Exchange an auth request ID for tokens
To get an access token and ID token as the RP, poll the /oauth2/access_token endpoint with HTTP POST requests having the following parameters:
-
grant_type=urn:openid:params:grant-type:ciba
-
auth_req_id=<auth-req-id>
For example:
$ curl \
--request POST \
--user '<rp-client-id>:<rp-client-secret>' \
--data 'grant_type=urn:openid:params:grant-type:ciba' \
--data 'auth_req_id=<auth-req-id>' \
'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/access_token'
The response depends on the end user and the polling interval:
-
After the end user has authorized the operation, AM returns an ID token and an access token:
{ "access_token": "<access-token>", "refresh_token": "<refresh-token>", "scope": "openid profile", "id_token": "<id-token>", "token_type": "Bearer", "expires_in": 3599 }
-
Before the end user authorizes the operation, AM returns an HTTP 400 Bad Request status:
{ "error_description": "End user has not yet been authenticated", "error": "authorization_pending" }
-
The auth ID response includes a polling
interval
. The RP must waitinterval
seconds before retrying the request (default: two seconds). If the RP does not wait long enough between retries, AM returns an HTTP 400 Bad Request status:{ "error_description": "The polling interval has not elapsed since the last request", "error": "slow_down" }
Additional OIDC claims
An RP can request additional claims about the end user with the access token at the /oauth2/userinfo endpoint:
$ curl \
--request GET \
--header "Authorization Bearer <access-token>" \
"https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/userinfo"
{
"name": "<end-user-display-name>",
"family_name": "<end-user-family-name>",
"given_name": "<end-user-given-name>",
"sub": "<end-user-id>",
"subname": "<end-user-id>"
}
Hybrid grant
- Endpoints
OpenID Connect (OIDC) authentication using the hybrid flow lets a relying party (RP) choose when to request access and ID tokens.
The hybrid grant flow is a two-step process:
-
The RP first requests a code and tokens by setting the response type:
Response type OpenID provider (OP) returns code id_token
An authorization code and an ID token
code token
An authorization code and an access token
code token id_token
An authorization code, and access token, and an ID token
AM returns the code and the requested tokens in the fragment of the redirection URL.
-
After the first request but before the authorization code expires (default: 120 seconds), the RP makes a second request to exchange the authorization code for additional tokens.
Follow these security recommendations when implementing the hybrid flow:
|
-
The end user wants to access services the RP provides. The RP requires an account to provide access to the services.
The end user makes a request to the RP to access their information stored at the OP.
-
To access the end user’s information at the OP, the RP needs authorization from the end user. The RP redirects the end user’s browser…
-
…to the OP.
-
The OP authenticates the end user, confirms resource access, and gathers consent if necessary.
-
On success, the OP redirects the end user to the RP.
-
The OP appends an authorization code and tokens to the URL fragment.
-
The RP stores the authorization code for future use and validates the ID token to get the subject ID.
-
With the ID token, the RP provides services to the end user.
-
Before the authorization code expires, the RP exchanges it for an access token, which the RP can use to get more information about the end user.
-
AM returns an access token.
-
The RP sends a request to the /oauth2/userinfo endpoint with the access token for authorization.
-
If the access token is valid, the
/oauth2/userinfo
endpoint returns any additional claims.The RP can use the subject ID and the additional claims to identify the end user.
Demonstrate the flow
Prepare the demonstration
Complete these steps to prepare the hybrid flow demonstration:
-
Register the RP as a confidential client application with the following settings:
- Client ID
-
myClient
- Client Secret
-
forgerock
- Redirection URIs
-
https://www.example.com:443/callback
- Scopes
-
openid
profile
-
On the Core tab of the client profile, update this setting as appropriate for your use case and save your changes:
- Authorization code lifetime (seconds)
-
Default: 120
-
Switch to the Advanced tab of the client profile and add these settings:
- Grant Types
-
Authorization Code
Implicit
- Response Types
-
code id_token
code token
code token id_token
-
Save your changes to the client profile.
-
Create an end user profile and record the username and password.
Get a code and an ID token using a browser
-
As RP, browse to the /oauth2/authorize endpoint with at least the following parameters:
-
client_id:
myClient
-
response_type:
code id_token
-
scope:
openid profile
-
redirect_uri:
https://www.example.com:443/callback
For example:
https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize \ ?client_id=myClient \ &response_type=code%20id_token \ &scope=openid%20profile \ &state=abc123 \ &nonce=123abc \ &redirect_uri=https://www.example.com:443/callback
The URL is split and spaces added for readability purposes.
The
scope
parameter is optional if default values are configured in the authorization server or the client.The
state
andnonce
parameters are optional and included to protect against CSRF attacks. -
-
Sign in as the end user and grant consent if necessary.
AM redirects to the
redirect_uri
. -
Inspect the URL in the browser:
https://www.example.com:443/callback#code=<authorization-code>&id_token=<id-token>…
Get a code and an ID token using REST
-
Authenticate as the end user:
$ curl \ -i \ --request POST \ --header "Content-Type: application/json" \ --header "X-OpenAM-Username: <end-user-id>" \ --header "X-OpenAM-Password: <end-user-password>" \ --header "Accept-API-Version: resource=2.0, protocol=1.0" \ 'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate' {"tokenId":"<tokenId>","successUrl":"/enduser/?realm=/alpha","realm":"/alpha"}
-
As RP, make an HTTP POST request to the /oauth2/authorize endpoint with the following parameters:
-
scope:
openid profile
-
response_type:
code id_token
-
client_id:
myClient
-
csrf:
<tokenId>
-
redirect_uri:
https://www.example.com:443/callback
-
decision:
allow
For example:
$ curl \ --dump-header - \ --request POST \ --Cookie "iPlanetDirectoryPro=<tokenId>" \ --data "scope=openid profile" \ --data "response_type=code id_token" \ --data "client_id=myClient" \ --data "csrf=<tokenId>" \ --data "redirect_uri=https://www.example.com:443/callback" \ --data "state=abc123" \ --data "nonce=123abc" \ --data "decision=allow" \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize"
The URL is split and spaces added for readability purposes.
The
scope
parameter is optional if default values are configured in the authorization server or the client.The
state
andnonce
parameters are optional and included to protect against CSRF attacks.AM returns an HTTP 302 response with the code and ID token in the redirection URL fragment:
HTTP/1.1 302 Found … Location: https://www.example.com:443/callback#code=<authorization-code>&id_token=<id-token>… …
-
Exchange the code for an access token
Choose one of the following options:
-
Use the authorization code grant to exchange an authorization code for an access token.
-
Use the authorization code grant with PKCE to exchange an authorization code for an access token.
Additional OIDC claims
An RP can request additional claims about the end user with the access token at the /oauth2/userinfo endpoint:
$ curl \
--request GET \
--header "Authorization Bearer <access-token>" \
"https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/userinfo"
{
"name": "<end-user-display-name>",
"family_name": "<end-user-family-name>",
"given_name": "<end-user-given-name>",
"sub": "<end-user-id>",
"subname": "<end-user-id>"
}
OIDC user sessions
Logging in to the OpenID provider and obtaining tokens are established processes in the OpenID specification; however, keeping the relying party informed of the session’s validity is not as straightforward. The end user’s session in AM is unavailable to the relying party. The only information the relying party has is the expiration time of the ID token, which might be undesirable.
To solve this problem, AM supports the following OIDC specifications:
Session management
The OpenID Connect (OIDC) session management 1.0 draft series defines a mechanism for a relying party (RP) to:
-
Get an OpenID provider (OP) to confirm whether an OIDC session is valid based on an ID token.
-
Terminate an end user session with the OP; for example, when the user signs out.
The process is transparent to the end user.
An RP uses a hidden <iframe>
to get the session state from the OP and take action when the state changes.
AM supports these drafts of the specification:
Each version uses different endpoints to achieve the same result.
Session management draft 10
Draft 10 does not specify any session-related endpoints. AM’s implementation of Draft 10 depends on these endpoints:
- /oauth2/authorize
-
Retrieve session state.
- /json/sessions
-
Terminate an end user session.
Draft 10 flow
To check session state, create an <iframe>
in your RP
whose src
attribute targets the /oauth2/authorize
endpoint with the required parameters.
The user-agent sends the tenant session cookie with the request.
For example, a public client RP called myClient
uses the following <iframe src>
URL to request session state:
https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize \
?client_id=myClient \
&response_type=none \
&id_token_hint=<id-token> \
&redirect_uri=https://www.example.com:443/callback \
&prompt=none
The query string parameters include these settings:
prompt=none
-
Do not display user interaction pages to the end user.
id_token_hint=<id-token>
-
The ID token to validate against the end user’s session.
response_type=none
-
Do not issue a token in the response.
The following table lists the responses:
AM responses | Request with redirect_uri |
Request without redirect_uri |
---|---|---|
Valid session |
Redirect to |
Return HTTP 204 No Content. |
Invalid session |
Redirect to |
Return HTTP 400 Bad Request and redirect to a page that displays a message such as
|
The RP’s <iframe>
and the redirect_uri
page must process any errors;
for example, by redirecting the end user to sign in.
Enable draft 10 support
To enable draft 10 support for a realm, configure the OAuth 2.0 provider:
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider.
-
Switch to the Advanced tab and add
none|org.forgerock.oauth2.core.NoneResponseTypeHandler
to the Response Type Plugins settings. -
Save your changes.
To enable draft 10 support in the RP client profile:
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients > Client ID > Advanced.
-
In Response Types, add
none
. -
Save your changes.
Session management draft 05
Draft 05 defines two endpoints for session management. These endpoints are no longer present in draft 10:
- /oauth2/connect/checkSession
-
Retrieve session state.
- /oauth2/connect/endSession
-
Terminate an end user session and redirect to a post-logout page.
Enable draft 05 support
The /oauth2/connect/checkSession endpoint serves as the check_session_iframe
URL.
To enable draft 05 support in the RP client profile:
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients > Client ID > OpenID Connect.
-
In Client Session URI, add the URL the RP uses as the
<iframe src>
URL. -
Save your changes.
Disable session management
By default, the AM OP supports draft 05 without additional configuration.
To disable session management support for a realm, configure the OAuth 2.0 provider:
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
Clear Enable Session Management.
-
Save your changes.
This also disables backchannel logout.
Backchannel logout
OpenID Connect Back-Channel Logout 1.0 Draft 06 defines how a provider can send a logout token to the relevant relying parties when an end user session linked to an ID token becomes invalid.
When backchannel logout is enabled, AM sends a logout token to a URL configured in the relying party’s client profile. This URL must be a page or application in the relying party that is capable of dealing with the token.
AM stores a list of logged in clients in the end user’s session so that, when it becomes invalid, AM has a list of URLs to which it needs to send the logout token to.
This is particularly important in scenarios where different relying parties use the same user session to obtain ID tokens. By storing the URLs in the session itself, AM ensures that all the related relying parties receive a logout token.
Next, the relying party validates the logout token, and clears any state associated with the combination of session ID, user, and issuer. Finally, it sends a response to AM with the outcome of the logout, as explained in 2.8 Back-Channel Logout Response of the draft.
Depending on which status code AM receives,
it logs an audit event of the type AM-BACK-CHANNEL-LOGOUT
in the activity log file, which resembles the following:
{
"_id":"cb52bc45-549d-4a9c-86cc-20d7500e333b-96127",
"eventName":"AM-BACK-CHANNEL-LOGOUT",
"transactionId":"cb52bc45-549d-4a9c-86cc-20d7500e333b-94750",
...
...
"operation":"Sent logout request to https://rp.example.com:8443/logout, which responded with HTTP code 200.",
...
}
AM will log the HTTP code that the relying party returns, or an error if there is no response before the request times out.
The following simplified diagram illustrates a possible backchannel logout flow:
Backchannel logout limitations
The current implementation of backchannel logout in AM has the following limitations:
-
It is only supported for server-side sessions.
-
AM currently only supports backchannel logout when acting as the provider.
The logout token
The logout token is defined in section 2.4 Logout Token of the draft. The following is an example logout token issued by AM, and the description of its claims:
{ "aud": "backchannelConfidentialClient", (1) "sub": "(usr!ForgerockDemo)", (2) "auditTrackingId": "cb52bc45-549d-4a9c-86cc-20d7500e333b-91288", (3) "iss": "https://openam.example.com:8443/openam/oauth2/backchannelSubRealm", (4) "cause": "CLIENT_LOGOUT", (5) "iat": 1614005410, (6) "jti": "1cd8805d-6fc0-4699-a33f-a75d45b24e9e", (7) "events": { (8) "http://schemas.openid.net/event/backchannel-logout": {} }, "sid": "mTNo042FCiPkgAJKjdjgCvBWvVYTB1d+zreDBnZAqvM=" (9) }
1 | Specifies the audience of the logout token. In this case, the client that requested the ID token(s) related to the user that has been logged out. |
2 | Specifies the subject of the logout token. In this case, the user that has been logged out. The subject of the logout token matches the subject of the ID token(s). |
3 | (AM-specific) Determines the unique audit identifier for this token. |
4 | Specifies the authorization server that issued the logout token. |
5 | (AM-specific) Documents the reason why the user was logged out, if known.
Possible values are:
|
6 | Specifies the creation time of the logout token. |
7 | Specifies the unique identifier for the logout token. |
8 | Specifies a JSON object that contains the http://schemas.openid.net/event/backchannel-logout URL,
which marks the JWT as a logout token.
The value of the object is always an empty JSON object ({}). |
9 | Specifies a session ID that identifies the relying party’s session with the provider.
The sid in the logout token matches the sid in the related ID token,
and therefore, the relying party can match both when doing session clean up operations.
If a relying party requests several ID tokens using the same end user session, they will all share the same sid .
However, if several relying parties use the same user session to obtain ID tokens, the sid in them will be different.
When the end user’s session becomes invalid, AM will send logout tokens to all the relying parties involved.
Note that the claim is only populated in the logout token
if Backchannel Logout Session Required is enabled in the client profile.
See Enable backchannel logout. |
Enable backchannel logout
To enable backchannel logout, first configure the OAuth 2.0 provider for the realm, and next configure the clients that will use the feature:
-
Configure the OAuth 2.0 provider:
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
Enable OIDC Session Management , if it is not already enabled.
OIDC Session Management is enabled by default, and it is also required for Session Management.
When enabled, AM will always add a
sid
to the ID tokens, regardless of whether clients have logout URLs configured in them or not. -
Save your changes.
-
Review the logout token signing secret.
AM signs logout tokens with the same secret it uses to sign ID tokens. For more information, see Secret ID mappings for signing OpenID Connect tokens.
-
Configure AM to encrypt the logout tokens.
Encryption is disabled by default. To enable it, you must configure ID token encryption as well. For more information, see Encrypt ID tokens and backchannel logout tokens.
-
-
Configure the clients:
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients > Client ID > OpenID Connect.
-
In the Back Channel Logout URI field, set the URL in the relying party to where AM will send the logout token during backchannel logout.
This URL can use the http or the https schemes, 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:8443/logout
. -
If the logout token must contain the session ID (
sid
), enable Backchannel Logout Session Required. -
Save your changes, and configure as many clients as required.
Clients registering dynamically can provide their backchannel logout configuration, too.
-
The backchannel logout Postman collection
ForgeRock provides a backchannel logout Postman collection to try out the functionality. The source for the REST calls, including the prerequisites needed to run the collection, is provided as a downloadable JSON file collection.
Backchannel logout relies on a relying party that can acknowledge the logout token and send a response back to AM. To emulate this, you can send a mock server in Postman.
Perform the following steps to download, configure, and run the backchannel logout Postman collection:
-
Download and install Postman.
-
Download the ForgeRock OpenID Connect backchannel logout collection.
-
Import the collection in Postman:
-
Go to File > Import … > Upload Files.
-
Select the collection you downloaded, and click Open. Then, click Import.
-
-
Create a Postman mock server.
Follow the instructions in the Setting Up Mock Servers in the Postman Documentation.
The mock server will work as the relying party. Inspect the requests sent to the mock server to see the logout tokens sent by AM.
When you create a mock server, Postman presents you with some information and the URL you can use to call it. For example,
https://f4a08510-2f95-4990-8cb0-5a4f281a8bac.mock.pstmn.io
.Save this URL; you need to configure it in the following step of this procedure.
-
Configure the collection’s variables to suit your environment:
-
In Postman, on the Collections tab, select the ForgeRock OpenID Connect Backchannel Logout Collection. From the more options menu (
…
), select Edit. -
Click on the Variables tab, and change at least the value of the following variables:
-
URL_base
Configure the URL of your AM environment. For example,
https://openam.example.com:8443/openam
. -
admin_password
Configure the password of the administrative user, such as
amAdmin
, that the collection will use to create AM configuration objects. -
back_channel_logout_uri
Configure the backchannel logout URL of your relying party, or the URL of the Postman mock server.
-
-
Click Update to save your changes.
You are ready to start running the collection.
The collection is divided into the following folders:
-
Prerequisites
, containing REST calls to configure a new realm containing an authorization server, and to create the clients and users required to run the collection. -
OpenID Connect Backchannel Logout Flow
, containing REST calls for the authorization code grant flow, and to log out the demo user. -
Mock Response
, containing a REST call to send AM a response when using the mock server.
-
-
Run the collection.
-
(Mock server only) On the mockup server window, check the request body of the
Mock Up Response
to see the logout token.Example Postman Mock Up Server Window with the Response Body Expanded
-
Inspect the contents of the logout token.
Tokens created by the collection are not encrypted.
-
Open the AM activity audit log.
Check for an entry with event name
AM-BACK-CHANNEL-LOGOUT
with the logout request, and the relying party’s response. For example:{ "_id":"cb52bc45-549d-4a9c-86cc-20d7500e333b-96127", "eventName":"AM-BACK-CHANNEL-LOGOUT", "transactionId":"cb52bc45-549d-4a9c-86cc-20d7500e333b-94750", ... ... "operation":"Sent logout request to https://f4a08510-2f95-4990-8cb0-5a4f281a8bac.mock.pstmn.io, which responded with HTTP code 200." ... }
Authentication requirements
A relying party (RP) can have different authentication requirements for different protected resources. For example, a financial services provider accepts username and password authentication to create an account, but requires multi-factor authentication to download bank account statements.
AM lets you associate requirements with authentication journeys. RPs specify the authentication requirements in their requests, and AM uses the associations to authenticate the end user with the requested journey and honor the requirements.
AM communicates the honored requirements by optionally returning claims in ID tokens. It uses the following standard claims:
-
An authentication context class reference (
acr
) claim holds a case-sensitive string identifying the class of authentication methods or procedures the authentication process satisfied; for example, an identifier for the authentication journey the end user completed successfully. -
An authentication method references (
amr
) claim holds a JSON array of strings identifying the authentication methods satisfied; for example, an indication the end user has authenticated with a username-password combination and a one-time password.
The acr
claim
The acr
claim holds a case-sensitive string you configure in the OAuth 2.0 provider service.
AM maps acr
keys to authentication journeys to avoid directly exposing the journey names.
AM does not add the acr
claim to ID tokens by default.
The RP must request authentication contexts and AM must authenticate the end user.
The acr
claims can be voluntary or essential.
Voluntary claims
RPs request voluntary acr
claims for optional authentication mechanisms to improve the user experience.
They do this in one of the following ways:
-
Specify the authentication mechanism in the
acr_values
parameter for a request to the/oauth2/authorize
endpoint. -
Specify the authentication mechanisms in the JSON format
claims
parameter for a request to the/oauth2/authorize
endpoint. -
Rather than specifying the mechanisms in the request, rely on Default ACR values in the RP client profile.
Find the field in the AM admin UI under Realms > Realm Name > Applications > OAuth 2.0 > Client ID > OpenID Connect.
The default
acr
values are the keys of the mapping set when you Configureacr
claims. The JSON response from the /oauth2/.well-known/openid-configuration endpoint lists the keys asacr_values_supported
strings; for example:"acr_values_supported": ["username-password"]
Any mechanisms the RP specifies in the request override the default
acr
values.
Essential claims
RPs request essential acr
claims for required authentication mechanisms.
RPs request essential acr
claims by specifying the authentication mechanisms in the JSON format
claims
parameter for a request to the /oauth2/authorize
endpoint.
Essential claims resemble, but are unrelated to, step-up authentication.
Configure acr
claims
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
Enable Enable "claims_parameter_supported" to let RPs request
acr
claims using theclaims
parameter. -
In the OpenID Connect acr_values to Auth Chain Mapping box, map keys to authentication journey identifiers.
The following example maps
username-password
to the Login journey:The key for the journey AM use to authenticate the end user becomes the value of the
acr
claim in the resulting ID token. -
Save your changes.
Request processing
When an RP requests authentication contexts, AM initially determines the requested journey.
It uses the first context for which it has a valid mapping.
For example, if the RP requests push otp username-password
and AM has mappings only for otp
and username-password
,
AM chooses otp
to authenticate the end user.
The following table describes how AM processes the request:
Scenario | Voluntary claims result | Essential claims result |
---|---|---|
The end user is not authenticated. |
Authenticate with the requested journey. |
Authenticate with the requested journey. |
The end user is authenticated with the requested journey. |
Do not re-authenticate. |
Re-authenticate with the requested journey. On success, delete the original session and create a new session. |
The end user is authenticated with a different journey. |
Re-authenticate with the requested journey. On success, delete the original session and create a new session. |
|
The request specifies an unmapped |
Continue the grant flow without returning an error. |
Return an error and redirect to the |
After authenticating the end user, AM returns an ID token whose acr
claim has one of the following values:
0
(zero)-
The RP requested an unmapped voluntary claim.
acr-key
-
The end user authenticated with the journey mapped to acr-key.
If authentication involves more than one journey, the acr-key reflects the last mapped journey.
The amr
claim
The amr
claim holds an array of strings identifying families of authentication methods.
Because authentication nodes are not used on their own but as part of an authentication journey,
you cannot map amr
values to specific authentication nodes.
However, you can map an AuthType
session property to amr
values using the Set Session Properties node.
When the end user authenticates with a journey using the node,
AM includes the amr
claim in the ID token it issues.
Configure amr
claims
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
In the OpenID Connect id_token amr Values to Auth Module Mappings box, map an identifier (the key in the map) to any authentication module.
The authentication module you use is not important; AM only uses its name to map the amr, and it won’t show in the ID token.
Example: Mapping authentication modules to amr identifiers
In this example, we map the identifier to the LDAP authentication module:
-
Save your changes.
-
Go to Realms > Realm Name > Services and add a Session Property Whitelist service.
-
Add
AuthType
to the Allowlisted Session Property Names field. This ensures the property can be read, edited, or deleted, from a session. -
Save your changes.
-
Create or update an authentication journey to include a Set Session Properties node.
-
On the Set Session Properties node, configure a key called
AuthType
.As its value, set the name of the authentication module you configured with the amr mapping. For example,
LDAP
.Example: Configuring the AuthType session property
To reference multiple authentication modules, separate amr values with
|
. For example, if both the LDAP and the DataStore modules are mapped to amr values, set theAuthType
key to the valueLDAP|DataStore
. -
Save your changes.
Demonstrate authentication requirements
Demonstrate the process with an RP that uses the Implicit grant:
-
Create an end user profile and record the username and password.
-
Duplicate the default Example journey to create a Login journey.
-
Optionally Configure
amr
claims. -
Configure
acr
claims to map your duplicate journey to theusername-password
claim.
Create an RP profile
Register an OIDC application with the following settings:
Setting |
Value |
Name |
|
Redirection URIs |
Add |
Scopes |
|
Advanced > Grant Types |
Add |
Request voluntary claims
-
Open a new tab in your browser.
-
Paste a URL with the
acr_values
parameter to request voluntary claims into the new browser tab:The following URL requests an ID token with the implicit grant:
https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize?acr_values=username-password&client_id=myClient&response_type=id_token&scope=openid%20profile&redirect_uri=https://www.example.com:443/callback&nonce=abc123&state=123abc
-
Authenticate as the end user.
AM redirects to the application sign-in URL (
redirect_uri
) with theid_token
in the fragment. -
Extract the ID token from the sign-in URL.
-
Decode the ID token to display the
acr
claim:{ "...": "...", "acr": "username-password" }
The
amr
claim is also displayed in the decoded token if you configuredamr
claims, for example:"amr": [ "PWD" ],
Request essential claims
-
Define and URL-encode the essential claims parameter value.
Essential claims requesting
username-password
:{"id_token":{"acr":{"essential":true,"values":["username-password"]}}}
URL-encoded value:
%7B%22id_token%22%3A%7B%22acr%22%3A%7B%22essential%22%3Atrue%2C%22values%22%3A%5B%22username-password%22%5D%7D%7D%7D
-
Paste a URL with the encoded
claims
parameter to request essential claims into the new browser tab:The following URL requests an ID token with the implicit grant:
https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize?claims=%7B%22id_token%22%3A%7B%22acr%22%3A%7B%22essential%22%3Atrue%2C%22values%22%3A%5B%22username-password%22%5D%7D%7D%7D&client_id=myClient&response_type=id_token&scope=openid%20profile&redirect_uri=https://www.example.com:443/callback&nonce=abc123&state=123abc&prompt=login
The
prompt
setting forces the end user to authenticate explicitly regardless of any implied consent.When you request essential claims, AM authenticates the end user again. For details, refer to Request processing.
AM redirects to the application sign-in URL (
redirect_uri
) with theid_token
in the fragment. -
Extract the ID token from the sign-in URL.
-
Decode the ID token to display the
acr
claim:{ "...": "...", "acr": "username-password" }
GSMA Mobile Connect
GSMA Mobile Connect is an application of OpenID Connect (OIDC). It enables mobile phones to serve as authentication devices independently of the service and the device.
Mobile Connect offers a standard way for Mobile Network Operators (MNOs) to act as general-purpose identity providers. It offers a range of Levels of Assurance (LoAs) and profile data to Mobile Connect-compliant service providers.
Mobile Connect roles
In a Mobile Connect deployment, AM can play the following roles:
- The OpenID provider
-
The provider implements the Mobile Connect Profile as part of the Service Provider (Identity Gateway interface).
The OpenID provider responds to a successful authorization request with all the required fields and the optional
expires_in
field. AM supports the mandatory ID Token properties. The relying party must use theexpires_in
value instead of specifyingmax_age
as a request parameter.AM returns the standard
userinfo
claims and theupdated_at
property. Theupdated_at
property holds the time last updated as seconds since January 1, 1970 UTC. - The authenticator
-
The authenticator implements the Mobile Connect Profile as part of the Identity Gateway (Authenticators interface).
The authenticator makes users authenticate at the appropriate LoA. A service provider can request LoAs without regard to the implementation. The Identity Gateway includes a claim in the ID Token to indicate the LoA achieved.
LoA support
AM maps LoAs to an authentication mechanism:
-
A service provider acting as a relying party requests an LoA with the
acr_values
parameter. -
AM returns the corresponding
acr
claim in the ID token.
LoA support:
-
1
(low—little or no confidence) -
2
(medium—some confidence, as in single-factor authentication) -
3
(high—high confidence, as in multi-factor authentication)
LoA support does not include support for 4
, which involves digital signatures.
The dtbs
authorization parameter is not supported.
Configure Mobile Connect
-
Configure the OAuth 2.0 provider OIDC authentication context settings to return
acr
andamr
claims in the ID tokens.For details, refer to Authentication requirements.
-
Update the identity store user configuration.
The
userinfo
endpoint returnsupdated_at
values in the ID token. If the user profile has never been updatedupdated_at
reflects creation time.When using DS as an identity store, AM takes
updated_at
from themodifyTimestamp
attribute if it exists, and thecreateTimestamp
attribute if not.In the AM admin UI, go to Realms > Realm Name > Identity Stores > Identity Store Name > User Configuration and add the relevant attributes to the LDAP User Attributes list.
-
Save your work.
Authorization parameters
You must use the authorization code grant to request ID tokens.
Request parameter | Supported? | Description |
---|---|---|
|
Yes |
The OpenID Connect authentication context class reference values. For details, refer to The |
|
Yes |
A unique string identifier for the application making the request. |
|
Yes |
A string value specifying the user interface display. |
|
No |
Data to be signed. LoA 4 is not supported. |
|
Yes |
A string specifying the ID used to log in. Set the |
|
Yes |
A string linking the client session with the ID token to mitigate against replay attacks. Required for Mobile Connect. |
|
Yes |
The URI to return the end user to after authorization is complete;
must match the |
|
Yes |
A string specifying the response expected from the authorization server; use |
|
Yes |
A string specifying the permissions the client application requests from the end user. Separate scopes with spaces. Required: Optional: |
|
Yes |
A string value to maintain state between the request and the callback. Required for Mobile Connect. |
ID token uses
ID tokens can also serve as session cookies and as policy subjects.
As session cookies
You can enable trusted client applications to use ID tokens as session cookies for calls to REST endpoints.
-
Clients must get the ID token with the authorization code grant flow.
-
Clients can use refresh tokens to get a new ID token, but the session lifetime still applies.
When the session expires, even a valid ID token is no longer a valid session cookie. The end user must authenticate again to get a new session.
To enable trusted clients to use ID tokens as session cookies:
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
In the Authorized OIDC SSO Clients field, add the client IDs for all trusted clients.
These trusted clients act with the full authority of the end user.
-
Ensure that Enable Session Management is enabled.
-
Save your changes.
As policy subjects
An ID token can serve as a subject condition for policies validating the token’s claims.
For example, a policy can validate that the token audience belongs to a specific group of applications
by checking the aud
claim to ensure it includes samplePolicySet
.
Policy evaluation only validates the claims, not the ID token. Validate the ID token before making the policy evaluation request.
To configure a policy that validates claims, define a subject condition with the OpenID Connect/Jwt Claim type.
Example
The following example shows a policy evaluation request with an ID token as a session cookie and as a subject.
The end user must have the |
$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "Accept-API-Version: protocol=1.0,resource=2.0" \
--header "iPlanetDirectoryPro: <id-token>" \
--data '{
"resources": ["https://www.example.com:8443/index.html"],
"subject": {
"ssoToken": "<id-token>"
},
"application": "samplePolicySet"
}' \
"https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies?_action=evaluate"
OpenID Connect 1.0 endpoints
Your applications can use the following OpenID Connect (OIDC) endpoints:
Endpoint | Description | AM is the… |
---|---|---|
Retrieve information about an authenticated end user
(UserInfo endpoint);
requires a valid token with at least the |
Provider |
|
Validate an unencrypted ID token (AM-specific endpoint). |
Provider |
|
Retrieve OpenID Connect session information (session management endpoint). |
Provider |
|
Terminate an OpenID Connect session (session management endpoint). |
Provider |
|
Register, read, or delete a client profile (dynamic client registration endpoint) |
Provider |
|
Let a client application discover the OpenID provider URL of an end user (WebFinger discovery endpoint). |
Provider |
|
Let a relying party discover the OpenID provider configuration. |
Provider |
|
Retrieve the OpenID provider’s public keys to verify client-side token signatures or to encrypt OIDC JWTs in requests. |
Provider |
|
Retrieve AM client public keys for providers to encrypt ID tokens and verify signatures. |
Relying party |
Many OAuth 2.0 endpoints also support OIDC. For reference documentation, refer to:
/oauth2/userinfo
The /oauth2/userinfo
endpoint is the OpenID Connect (OIDC)
UserInfo endpoint.
Use this endpoint to request claims about the authenticated end user.
Specify the realm in the request URL; for example:
https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/userinfo
To access the endpoint, use an access token from an OIDC grant flow as the bearer token. The endpoint returns claims based on the scopes granted for the access token as in the following example:
$ curl \
--request GET \
--header "Authorization: Bearer <access-token>" \
"https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/userinfo"
{
"name": "Babs Jensen",
"family_name": "Jensen",
"given_name": "Babs",
"sub": "a0325ea4-9d9b-4056-931b-ab64704cc3da",
"subname": "a0325ea4-9d9b-4056-931b-ab64704cc3da"
}
Subject claims
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)
.
The value of the subname
claim matches the value of the subject portion of the sub
claim.
Response signing and encryption
The default response is a plain JSON object.
AM also supports responding with a signed JSON Web Token (JWT) or signed and encrypted JWT.
JWT responses include the aud
and iss
claims.
To enable signing and encryption, follow these steps:
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients > Client ID > Signing and Encryption and select the response type in the User info response format drop-down list.
-
If necessary, configure the signing and encryption properties:
User info signed response algorithm
User info encrypted response algorithm
User info encrypted response encryption algorithm -
Save your work.
-
To restrict the possible settings for the clients in the realm, edit the settings under Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
Save your work.
For details, refer to the OAuth 2.0 provider reference documentation for advanced OIDC settings and to Secret ID default mappings.
/oauth2/idtokeninfo
The /oauth2/idtokeninfo
endpoint is an AM-specific endpoint.
Use this endpoint to validate unencrypted ID tokens and to retrieve claims in the token.
Specify the realm in the request URL; for example:
https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/idtokeninfo
Supported parameters
The ID token information endpoint supports the following parameters:
Parameter | Description | Required |
---|---|---|
|
Comma-separated list of claims to return from the ID token. |
Yes |
A signed JSON Web Token (JWT) to use as client credentials. |
Yes, for JWT profile authentication |
|
The type of assertion, |
Yes, for JWT profile authentication |
|
Uniquely identifies the application making the request. |
Yes, when authentication is required (default) |
|
The password for a confidential client. |
Yes, when authenticating with Form parameters (HTTP POST) |
|
|
The ID token to validate. |
Yes |
By default, the client must authenticate to use the endpoint. Optionally disable this in the OAuth 2.0 provider configuration. In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect and disable Idtokeninfo Endpoint Requires Client Authentication.
Token validation
AM validates the tokens based on rules in the OpenID Connect Core specification. Token validation includes the following steps:
-
Extract the first
aud
(audience) claim from the ID token.This step depends on the
client_id
parameter to identify the client and validate theaud
claim. -
Extract the
realm
claim, if present, and use it to look up the client profile.Validation returns an error if no client profile exists.
-
Verify the signature of the ID token.
This validation step depends on these client profile settings:
ID Token Signing Algorithm (default:
RS256
)
Public key selector (default:JWKs_URI
) -
Verify the following claims:
aud
(audience)
exp
(expiration)
iat
(issued at)
iss
(issuer)
nbf
(not before, if set)
This endpoint does not check whether the ID token was revoked with the /oauth2/connect/endSession endpoint.
Examples
The following example returns all ID token claims:
$ curl \
--request POST \
--user myClient:forgerock \
--data 'id_token=id-token' \
"https://openam.example.com:8443/openam/oauth2/idtokeninfo"
{
"at_hash": "PZg5xZsIlFtRSfg8MAWhWg",
"sub": "a0325ea4-9d9b-4056-931b-ab64704cc3da",
"auditTrackingId": "2e5c7611-4a61-4001-8739-f714d43e9da2-881454",
"subname": "a0325ea4-9d9b-4056-931b-ab64704cc3da",
"iss": "{exampleUrl/oauth2/realms/root/realms/alpha",
"tokenName": "id_token",
"given_name": "Babs",
"sid": "+buKyDp+Fbc0/Rkd0OqsfdKy7ZY0nWvcsEetikX+eTc=",
"aud": "myClient",
"c_hash": "FP5Nj162jgycmtEeRjVQ-A",
"acr": "0",
"org.forgerock.openidconnect.ops": "gkQOcZ1F3ZFdYPd6TiGIgr6scH0",
"s_hash": "bKE9UspwyIPg8LsQHkJaiQ",
"azp": "myClient",
"auth_time": 1676360741,
"name": "Babs Jensen",
"realm": "/alpha",
"exp": 1676364398,
"tokenType": "JWTToken",
"iat": 1676360798,
"family_name": "Jensen"
}
Use the optional claims
parameter to return specific claims as in the following example:
$ curl \
--request POST \
--user myClient:forgerock \
--data 'id_token=id-token' \
--data 'claims=sub,exp,realm' \
"https://openam.example.com:8443/openam/oauth2/idtokeninfo"
{
"sub": "a0325ea4-9d9b-4056-931b-ab64704cc3da",
"exp": 1676364398,
"realm": "/alpha"
}
If you request a claim that does not exist, no error occurs; AM omits the claim from the response.
Subject claims
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)
.
The value of the subname
claim, when provided, matches the value of the subject portion of the sub
claim.
/oauth2/connect/checkSession
The /oauth2/connect/checkSession
endpoint is defined in
OpenID Connect Session Management 1.0 - draft 5.
A relying party client creates an invisible iframe
with the URL to the endpoint as the src
attribute of the iframe
tag.
Use the endpoint to accept HTML5 postMessage
requests from the iframe
,
and to generate postMessage
requests to the iframe
with the end user’s login status.
For details on checking session state, refer to Session management.
Do not specify the realm in the request URL; for example:
https://openam.example.com:8443/openam/oauth2/connect/checkSession
/oauth2/connect/endSession
The /oauth2/connect/endSession
endpoint is defined in
OpenID Connect Session Management 1.0 - draft 5.
Use this endpoint to terminate authenticated end-user sessions. For details on ending session state, refer to Session management.
To find the URL for this endpoint, read the end_session_endpoint
field of the
well-known configuration endpoint for the realm:
$ curl https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/.well-known/openid-configuration
{
"…": "…",
"end_session_endpoint": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/connect/endSession",
"…": "…"
}
Supported parameters
The end session endpoint supports the following query parameters:
Parameter | Description | Required |
---|---|---|
Uniquely identifies the application making the request. This parameter is not compliant with the specification. |
Yes, when the ID token is encrypted |
|
Previously issued ID token identifying the end user’s session. |
Yes |
|
|
Redirect to this URI after logout. This must match one of the values in the Post Logout Redirect URIs setting of the client profile. By default, this profile setting is empty. To update the setting in the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Client ID > OpenID Connect. |
No |
The post_logout_redirect_uri
parameter determines the result on successful logout:
-
If included, AM redirects to the specified location.
-
If omitted, AM returns HTTP 204 No Content to indicate the end user logged out.
Example
AM deletes the end user’s session on successful logout and redirects to the post logout URL:
$ curl \
--dump-header - \
--request GET \
'https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/connect/endSession?id_token_hint=id-token&post_logout_redirect_uri=https://www.example.com/signout'
HTTP/2 302
…
location: https://www.example.com/signout
content-length: 0
…
/oauth2/register
The /oauth2/register
endpoint is defined in:
Use this endpoint to create, read, update, and delete client application profiles.
Specify the realm in the request URL; for example:
https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/register
The endpoint supports the following HTTP methods:
POST
-
Create a client profile.
GET
-
Read a client profile.
PUT
-
Update a client profile.
DELETE
-
Delete a client profile.
AM requires configuration to allow dynamic registration. For details, refer to Dynamic client registration.
/.well-known/webfinger
The /.well-known/webfinger
endpoint is described in
OpenID Connect Discovery 1.0 incorporating errata set 1.
Use it to discover the OpenID provider for an end user.
Do not specify the realm in the request URL; for example:
https://openam.example.com:8443/openam/.well-known/webfinger
This endpoint is disabled by default. For details, refer to OIDC discovery.
Supported parameters
The discovery endpoint supports the following parameters:
Parameter | Description | Required |
---|---|---|
|
The AM realm to query for the user profile. |
No |
|
The URI identifying the type of service. |
Yes; use |
|
The URL-encoded subject of the request.; one of:
The The |
Yes |
Example
$ curl \
'https://openam.example.com:8443/openam/.well-known/webfinger?resource=acct%3Abjensen%40example.com&rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer'
{
"subject": "acct:bjensen@example.com",
"links": [{
"rel": "http://openid.net/specs/connect/1.0/issuer",
"href": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha"
}]
}
/oauth2/.well-known/openid-configuration
The OpenID provider configuration endpoint is defined in OpenID Connect Discovery 1.0.
Use this to discover the provider settings. For details, refer to OIDC discovery.
Specify the realm in the request URL; for example:
$ curl https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/.well-known/openid-configuration
Show output
{
"request_parameter_supported": true,
"pushed_authorization_request_endpoint": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/par",
"introspection_encryption_alg_values_supported": ["ECDH-ES+A256KW", "ECDH-ES+A192KW", "RSA-OAEP", "ECDH-ES+A128KW", "RSA-OAEP-256", "A128KW", "A256KW", "ECDH-ES", "dir", "A192KW"],
"claims_parameter_supported": false,
"introspection_endpoint": "https://openam.example.com:8443/openam//oauth2/realms/root/realms/alpha/introspect",
"issuer": "https://openam.example.com:8443/openam//oauth2/realms/root/realms/alpha",
"id_token_encryption_enc_values_supported": ["A256GCM", "A192GCM", "A128GCM", "A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512"],
"userinfo_encryption_enc_values_supported": ["A256GCM", "A192GCM", "A128GCM", "A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512"],
"authorization_endpoint": "https://openam.example.com:8443/openam//oauth2/realms/root/realms/alpha/authorize",
"authorization_encryption_alg_values_supported": ["ECDH-ES+A256KW", "ECDH-ES+A192KW", "RSA-OAEP", "ECDH-ES+A128KW", "RSA-OAEP-256", "A128KW", "A256KW", "ECDH-ES", "dir", "A192KW"],
"introspection_encryption_enc_values_supported": ["A256GCM", "A192GCM", "A128GCM", "A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512"],
"claims_supported": [],
"rcs_request_signing_alg_values_supported": ["PS384", "ES384", "RS384", "HS256", "HS512", "ES256", "RS256", "HS384", "ES512", "PS256", "PS512", "RS512"],
"token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "self_signed_tls_client_auth", "tls_client_auth", "none", "client_secret_basic"],
"tls_client_certificate_bound_access_tokens": true,
"response_modes_supported": ["fragment", "jwt", "form_post.jwt", "form_post", "fragment.jwt", "query", "query.jwt"],
"backchannel_logout_session_supported": true,
"token_endpoint": "https://openam.example.com:8443/openam//oauth2/realms/root/realms/alpha/access_token",
"response_types_supported": ["code token id_token", "code", "code id_token", "device_code", "id_token", "code token", "token", "token id_token"],
"authorization_encryption_enc_values_supported": ["A256GCM", "A192GCM", "A128GCM", "A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512"],
"revocation_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "self_signed_tls_client_auth", "tls_client_auth", "none", "client_secret_basic"],
"request_uri_parameter_supported": true,
"grant_types_supported": ["implicit", "urn:ietf:params:oauth:grant-type:saml2-bearer", "refresh_token", "password", "client_credentials", "urn:ietf:params:oauth:grant-type:device_code", "authorization_code", "urn:openid:params:grant-type:ciba", "urn:ietf:params:oauth:grant-type:uma-ticket", "urn:ietf:params:oauth:grant-type:jwt-bearer"],
"version": "3.0",
"userinfo_endpoint": "https://openam.example.com:8443/openam//oauth2/realms/root/realms/alpha/userinfo",
"require_request_uri_registration": true,
"code_challenge_methods_supported": ["plain", "S256"],
"id_token_encryption_alg_values_supported": ["ECDH-ES+A256KW", "ECDH-ES+A192KW", "RSA-OAEP", "ECDH-ES+A128KW", "RSA-OAEP-256", "A128KW", "A256KW", "ECDH-ES", "dir", "A192KW"],
"authorization_signing_alg_values_supported": ["PS384", "RS384", "EdDSA", "ES384", "HS256", "HS512", "ES256", "RS256", "HS384", "ES512", "PS256", "PS512", "RS512"],
"request_object_signing_alg_values_supported": ["PS384", "ES384", "RS384", "HS256", "HS512", "ES256", "RS256", "HS384", "ES512", "PS256", "PS512", "RS512"],
"request_object_encryption_alg_values_supported": ["ECDH-ES+A256KW", "ECDH-ES+A192KW", "ECDH-ES+A128KW", "RSA-OAEP", "RSA-OAEP-256", "A128KW", "A256KW", "ECDH-ES", "dir", "A192KW"],
"rcs_response_signing_alg_values_supported": ["PS384", "ES384", "RS384", "HS256", "HS512", "ES256", "RS256", "HS384", "ES512", "PS256", "PS512", "RS512"],
"introspection_signing_alg_values_supported": ["PS384", "RS384", "EdDSA", "ES384", "HS256", "HS512", "ES256", "RS256", "HS384", "ES512", "PS256", "PS512", "RS512"],
"check_session_iframe": "https://openam.example.com:8443/openam//oauth2/realms/root/realms/alpha/connect/checkSession",
"scopes_supported": ["address", "phone", "openid", "profile", "fr:idm:*", "am-introspect-all-tokens", "email"],
"backchannel_logout_supported": true,
"acr_values_supported": [],
"request_object_encryption_enc_values_supported": ["A256GCM", "A192GCM", "A128GCM", "A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512"],
"rcs_request_encryption_alg_values_supported": ["ECDH-ES+A256KW", "ECDH-ES+A192KW", "RSA-OAEP", "ECDH-ES+A128KW", "RSA-OAEP-256", "A128KW", "A256KW", "ECDH-ES", "dir", "A192KW"],
"userinfo_signing_alg_values_supported": ["ES384", "HS256", "HS512", "ES256", "RS256", "HS384", "ES512"],
"require_pushed_authorization_requests": false,
"rcs_response_encryption_enc_values_supported": ["A256GCM", "A192GCM", "A128GCM", "A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512"],
"userinfo_encryption_alg_values_supported": ["ECDH-ES+A256KW", "ECDH-ES+A192KW", "RSA-OAEP", "ECDH-ES+A128KW", "RSA-OAEP-256", "A128KW", "A256KW", "ECDH-ES", "dir", "A192KW"],
"end_session_endpoint": "https://openam.example.com:8443/openam//oauth2/realms/root/realms/alpha/connect/endSession",
"rcs_request_encryption_enc_values_supported": ["A256GCM", "A192GCM", "A128GCM", "A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512"],
"revocation_endpoint": "https://openam.example.com:8443/openam//oauth2/realms/root/realms/alpha/token/revoke",
"rcs_response_encryption_alg_values_supported": ["ECDH-ES+A256KW", "ECDH-ES+A192KW", "ECDH-ES+A128KW", "RSA-OAEP", "RSA-OAEP-256", "A128KW", "A256KW", "ECDH-ES", "dir", "A192KW"],
"token_endpoint_auth_signing_alg_values_supported": ["PS384", "ES384", "RS384", "HS256", "HS512", "ES256", "RS256", "HS384", "ES512", "PS256", "PS512", "RS512"],
"jwks_uri": "https://openam.example.com:8443/openam//oauth2/realms/root/realms/alpha/connect/jwk_uri",
"subject_types_supported": ["public", "pairwise"],
"id_token_signing_alg_values_supported": ["PS384", "ES384", "RS384", "HS256", "HS512", "ES256", "RS256", "HS384", "ES512", "PS256", "PS512", "RS512"],
"registration_endpoint": "https://openam.example.com:8443/openam//oauth2/realms/root/realms/alpha/register"
}
/oauth2/connect/jwk_uri
Each realm configured for OAuth 2.0 exposes a JSON web key (JWK) URI endpoint that contains public keys that clients can use to:
-
Verify the signature of client-side access tokens and OpenID Connect ID tokens.
-
Encrypt OpenID Connect ID requests to AM sent as a JWT.
Where do the keys come from?
By default, the endpoint exposes an internal URI relative to the AM deployment.
For example, openam/oauth2/realms/root/connect/jwk_uri
.
The keys appearing in that URI are those configured in the AM secret stores, regardless of the algorithms configured in the OAuth 2.0 provider. This is to support the process of deprecating keys/algorithms.
Secrets are configured by default; delete the ones you are not planning to use so that they are not exposed on the endpoint.
In environments where secrets are centralized, you may want AM to share the URI of your secrets API instead of the local AM endpoint. To configure it, go to Realms > Realm Name > Services > OAuth2 Provider, and add the new URI to the Remote JSON Web Key URL field.
Note that HMAC-based algorithms, direct encryption, and AES key wrapping encryption algorithms use the client secret instead of a public key. Therefore, clients do not need to check the JWK URI endpoint for those algorithms.
The endpoint is exposed, but I haven’t configured an OAuth 2.0 provider yet
Web and Java agents use an internal OAuth 2.0 provider to connect to AM.
This provider exposes the endpoint so that agents can access the key configured
for the am.global.services.oauth2.oidc.agent.idtoken.signing
secret ID.
Configure the base URL source service
to change the URL used in the |
The following table summarizes the high-level tasks you need to complete to manage the JWK URI endpoint in your environment:
Task | Resources |
---|---|
Learn where to find and how to query the JWK URI endpoint. Clients need to find the endpoint to, for example, validate tokens signed by AM. |
|
Control which keys are displayed. The JWK URI endpoint returns keys based on the secret mappings configured for the relevant OAuth 2.0/OpenID connect functionality. Therefore, to control which keys are displayed, ensure that you only map the secrets required in your environment. |
|
Learn how to deprecate algorithms and how to rotate public keys. You may need to perform these tasks to replace algorithms with more secure ones. |
|
Customize the key ID ( By default, AM generates a You need to customize AM if any exposed keys in your environment need a specific |
|
Decide if the JWK URI endpoint should display duplicated key IDs By default, each If you have several algorithms and key types associated with one |
Access the keys exposed by the JWK URI endpoint
Perform the following steps to access the public keys:
-
To find the JWK URI that AM exposes, perform an HTTP GET at
/oauth2/realms/root/.well-known/openid-configuration
.For example:
$ curl https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/.well-known/openid-configuration { "request_parameter_supported": true, "claims_parameter_supported": false, "introspection_endpoint": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/introspect", "check_session_iframe": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/connect/checkSession", "scopes_supported": [], "issuer": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha", "id_token_encryption_enc_values_supported": [ "A256GCM", "A192GCM", "A128GCM", "A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512" ], … "jwks_uri": "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/connect/jwk_uri", "subject_types_supported": [ "public" ], … }
By default, AM exposes the JWK URI as an endpoint relative to the deployment URI. For example,
https://openam.example.com:8443/openam/oauth2/realms/root/connect/jwk_uri
.In environments where secrets are centralized, you may want AM to share the URI of your secrets API instead of the local AM endpoint.
To configure it, go to Realms > Realm Name > Services > OAuth2 Provider, and add the new URI to the Remote JSON Web Key URL field.
-
Perform an HTTP GET at the JWK URI to get the relevant public keys.
For example:
$ curl https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/connect/jwk_uri { "keys":[ { "kty":"EC", "kid":"I4x/IijvdDsUZMghwNq2gC/7pYQ=", "use":"sig", "x5t":"GxQ9K-sxpsH487eSkJ7lE_SQodk", "x5c":[ "MIIB/zCCAYYCCQDS7UWmBdQtETAJ0mN0TZL7/MaY…" ], "x":"k5wSvW_6JhOuCj-9PdDWdEA4oH90RSmC2GTliiUHAhXj6rmTdE2S-_zGmMFxufuV", "y":"XfbR-tRoVcZMCoUrkKtuZUIyfCgAy8b0FWnPZqevwpdoTzGQBOXSNi6uItN_o4tH", "crv":"P-384" }, … ] }
Configure ID token signatures
ID tokens are signed by default with a test key configured during installation. Change this key on production-like and production environments.
Perform the steps in this procedure to configure the signing algorithm AM should use to sign OpenID Connect tokens:
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider.
-
In the OpenID Connect tab, ensure that the ID Token Signing Algorithms supported list has the signing algorithms your environment requires.
AM supports the signing algorithms listed in JSON Web Algorithms (JWA): "alg" (Algorithm) Header Parameter Values for JWS.
Note that the alias mapped to the algorithms are defined in the secret stores, as shown in the table below:
Secret ID mappings for signing OpenID Connect tokens
The following table shows the secret ID mapping used to sign OpenID Connect ID tokens and backchannel logout tokens:
Secret ID Default alias Algorithms(1) am.services.oauth2.oidc.signing.ES256
es256test
ES256
am.services.oauth2.oidc.signing.ES384
es384test
ES384
am.services.oauth2.oidc.signing.ES512
es512test
ES512
am.services.oauth2.oidc.signing.RSA
rsajwtsigningkey
PS256
PS384
PS512
RS256
RS384
RS512am.services.oauth2.oidc.signing.EDDSA
EdDSA with SHA-512
(1) The following applies to confidential clients only:
If you select an HMAC algorithm for signing ID tokens (HS256, HS384, or HS512), the Client Secret property value in the OAuth 2.0 Client is used as the HMAC secret instead of an entry from the secret stores.
Since the HMAC secret is shared between AM and the 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.By default, secret IDs are mapped to demo keys contained in the default keystore provided with AM and mapped to the
default-keystore
keystore secret store. Use these keys for demo and test purposes only. For production environments, replace the secrets as required and create mappings for them in a secret store configured in AM.For more information about managing secret stores and mapping secret IDs to aliases, see Secrets, certificates, and keys.
-
If the client is configured in AM, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients > Client ID.
Clients registering dynamically can see the algorithms that the provider supports by making a call to the
/oauth2/.well-known/openid-configuration
endpoint. -
In the ID Token Signing Algorithm field, enter the signing algorithm that AM will use to sign the ID token for this client.
Note that the OAuth 2.0 provider must support signing with the chosen algorithm.
-
Save your changes.
AM is ready to sign ID tokens with the algorithm you configured.
If you chose a non-HMAC-based algorithm, the client will need to make a request to AM’s JWK URI endpoint for the realm to recover the signing public key they can use to validate the ID tokens.
Deprecate algorithms and rotate public keys
With signing and encryption methods changing so rapidly, during the lifecycle of your OAuth 2.0 environment you will need to deprecate older, less secure signing and/or encrypting algorithms in favor of new ones.
In the same way, you will rotate the keys AM uses for signing and encryption if you suspect they may have been leaked or just due to security policies, such as deprecating algorithms or because they have reached the end of their lifetime.
The keys you expose in the JWK URI endpoint should reflect the algorithms currently supported by AM as well as the deprecated ones. Otherwise, clients still using tokens signed with deprecated keys would not be able to validate them.
This is why deprecating supported algorithms in the OAuth 2.0/OpenID Connect provider is a two-step process:
-
Remove the old algorithm from the OAuth 2.0 provider supported algorithm list.
This stops new clients from registering with that algorithm.
-
After a grace period, remove the secret mapping associated to that algorithm.
This removes the associated public keys from the JWK URI endpoint.
Deprecate supported algorithms and their keys
Perform the steps in this procedure to deprecate an algorithm and its related keys. If you only want to deprecate keys or rotate them as part of your environment’s security policies, see Map and rotate secrets instead.
-
Configure the new algorithm, if required.
-
Go to Realms > Realm Name > Services > OAuth2 Provider > OpenID Connect.
-
In the ID Token Signing Algorithm supported field, add the new signing algorithm, if not already present.
-
In the ID Token Encryption Algorithms supported field, add the new encryption algorithm, if not already present.
-
Save your changes.
-
-
Configure secret ID mappings for the keys using the new algorithm, if required.
For more information, see Secret stores.
-
Remove the algorithm to be deprecated from the relevant OAuth 2.0 provider algorithm list:
-
Go to Realms > Realm Name > Services > OAuth2 Provider > OpenID Connect.
-
In the ID Token Signing Algorithm supported field, remove the deprecated signing algorithm.
-
In the ID Token Encryption Algorithms supported field, remove the deprecated encryption algorithm.
-
Save your changes.
-
-
Decide on a grace period.
For example, a month. During this period both the deprecated and the new algorithms/keys are supported.
New clients cannot register with the deprecated algorithms and are forced to use a supported algorithm. However, since the deprecated keys are still mapped to secret IDs, existing clients still can use them to validate active tokens and encrypt requests.
Existing clients must change their configuration during the grace period to use one of the supported algorithms.
-
After the grace period, remove the secret ID mappings relevant to the deprecated algorithm.
For more information about secret mappings, see Map and rotate secrets.
Customize public key IDs
By default, AM generates a key ID (kid
) for each public key exposed in the jwk_uri
URI
when AM is configured as an OAuth 2.0 authorization server.
For keys stored in a keystore or HSM secret store, you can customize how key ID values are determined
by writing an implementation of the KeyStoreKeyIdProvider
interface and configuring it in AM:
-
Write your own implementation of the
KeyStoreKeyIdProvider
interface that provides a specific key ID for a provided public key. For more information, see the KeyStoreKeyIdProvider interface in the Access Management Java API Specification. -
In the AM admin UI, configure the OAuth 2.0/OpenID Connect Provider service, if you haven’t already done so.
For more information, see Authorization server configuration.
-
Go to Configure > Server Defaults > Advanced.
-
Add an advanced server property called
org.forgerock.openam.secrets.keystore.keyid.provider
, whose value is the fully qualified name of the class you wrote in previous steps.For example:
org.forgerock.openam.secrets.keystore.keyid.provider = com.mycompany.am.secrets.CustomKeyStoreKeyIdProvider
-
Restart the AM instance or the container in which it runs.
-
Verify that the customized key IDs are displayed by navigating to the OAuth 2.0 authorization server’s
jwk_uri
URI.For example,
https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/connect/jwk_uri
.
Display every algorithm and key type associated with a key ID
By default, each key ID (kid
) exposed by the jwk_uri
endpoint matches a unique secret,
as recommended by the RFC7517 specification.
This means that each kid
is of a particular key type, and uses a particular algorithm.
If you have several algorithms and key types associated with one kid
,
configure the JWK URI endpoint to display them as different keys in the JWK.
Note that when including all combinations associated with a kid
,
that kid
does not uniquely identify a particular secret.
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
Enable Include all kty and alg combinations in jwk_uri.
-
Save your changes.
-
Verify that you can now see duplicate
kid
entries for different combinations of algorithms and key types.For more information, see Access the keys exposed by the JWK URI endpoint.
/oauth2/connect/rp/jwk_uri
As well as acting as the provider, AM can also act as the relying party. To share its client public secrets, AM exposes a JSON web key (JWK) URI endpoint for each realm.
Use this endpoint during ForgeRock Identity Platform social identity registration, where providers can use the exposed secrets to:
-
Encrypt ID tokens returned to AM.
-
Verify the signature of JWTs coming from AM, such as that of request objects or client authentication JWTs.
-
Decrypt client authentication JWTs coming from AM.
Specify the AM realm path in the URI, as follows:
/oauth2/realms/root/realms/alpha/connect/rp/jwk_uri
Example:
$ curl https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/connect/rp/jwk_uri
{
"keys": [
{
"kty": "RSA",
"kid": "DkKMPE7hFVEn77WWhVuzaoFp4O8=",
"use": "enc",
"x5t": "JRxY4hJRL3sI_dAUWUEosCEQJ3A",
"x5c": [
"MIIDYTCCAkm…eP4wLr3cM="
],
"n": "i7t6m4d_02dZ8dOe-DFc…zflF8jR9pewTbQ",
"e": "AQAB"
},
{
"kty": "RSA",
"kid": "wU3ifIIaLOUAReRB/FG6eM1P1QM=",
"use": "sig",
"x5t": "5eOfy1Nn2MMIKVRRkq0OgFAw348",
"x5c": [
"MIIDdzCCAl+gAwIBAgIES3eb+zANBgk…s009kbW6inN8zA6"
],
"n": "10iGQ5l5IdqB…AJW4ZSg1PPO2UJSQ",
"e": "AQAB"
}
]
}
Supply the JWK URI to the provider when registering AM as a relying party. Consult the documentation provided by your OpenID provider for more information.
The JWK URI endpoint publishes keys based on secret mappings made either globally, or in the specific realm.
The secret IDs to map are as follows:
am.services.oauth2.oidc.rp.jwt.authenticity.signing
-
The OpenID Connect provider obtains the public key from the alias mapped to this secret, and uses it to verify the signature applied to request objects it receives.
All aliases configured for the secret ID are published at the endpoint so that, when you rotate secrets, the provider is still able to validate JWTs with all the secrets.
The active secret is the only one that AM uses for signing, however.
am.services.oauth2.oidc.rp.idtoken.encryption
-
The OpenID Connect provider obtains the public key from the alias mapped to this secret, and uses it to encrypt ID tokens and
userinfo
endpoint data in JWT format before returning it to AM.Unlike the signing secret ID above, only the alias that is marked as active in the mappings is published at the endpoint. Any additional mappings are ignored.
am.services.oauth2.mtls.client.authentication
-
The OpenID Connect provider obtains the public JWK from the alias mapped to this secret, and uses it to verify the mutual TLS self-signed certificate that the client uses to authenticate.
Secrets configured globally will show in the JWK URI for all realms.
In a new installation of AM, these signing and encryption secret IDs are mapped by default, as explained in the table below:
Secret ID mappings for decrypting ID tokens
The following table shows the secret ID mapping to support decryption of ID tokens and userinfo
endpoint data
in JWT format when AM is configured as a relying party of the Social Identity Provider Service:
Secret ID | Default alias | Algorithms |
---|---|---|
|
|
Consult the |
The public key is exposed in the /oauth2/connect/rp/jwk_uri.
For more information about the algorithms supported, and how to configure this secret ID mapping, refer to Social authentication.
Secret ID mappings for signing JWTs and objects
The following table shows the secret ID mapping that AM uses to sign JWTs and objects when configured as a relying party of the Social Identity Provider Service:
Secret ID | Default alias | Algorithms |
---|---|---|
|
|
Consult the |
The public key is exposed in the /oauth2/connect/rp/jwk_uri.
For more information about the algorithms supported, and how to configure this secret ID mapping, refer to Social authentication.
In upgraded AM instances, the secret IDs will not have default aliases mapped, and the JWK URI endpoint returns an empty JWK set. |
By default, secret IDs are mapped to demo keys contained in the default keystore provided with AM
and mapped to the default-keystore
keystore secret store.
Use these keys for demo and test purposes only.
For production environments,
replace the secrets as required and create mappings for them in a secret store configured in AM.
For more information about managing secret stores and mapping secret IDs to aliases, see Secrets, certificates, and keys.