OIDC user info claims
This plugin extension point is invoked when issuing an ID token or during a
request to the /userinfo
OIDC endpoint. Use this script to retrieve
claim values based on an issued access token.
- Default script
-
To view the default script, including the available script properties, refer to oidc-claims-extension.groovy.
To view or modify the default script in the AM admin UI, go to Realms > Realm Name > Scripts and select OIDC Claims Script.
A JavaScript version of the script is also available: oidc-claims-extension.js. - Java interface
- Java sample
Show Sample Code
/*
* Copyright 2021-2022 ForgeRock AS. All Rights Reserved
*
* Use of this code requires a commercial software license with ForgeRock AS.
* or with one of its affiliates. All use shall be exclusively subject
* to such license between the licensee and ForgeRock AS.
*/
package org.forgerock.openam.examples;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.forgerock.oauth2.core.AccessToken;
import org.forgerock.oauth2.core.ClientRegistration;
import org.forgerock.oauth2.core.OAuth2Request;
import org.forgerock.oauth2.core.UserInfoClaims;
import org.forgerock.oauth2.core.plugins.UserInfoClaimsPlugin;
/**
* Custom implementation of the User Info Claims
* plugin interface {@link org.forgerock.oauth2.core.plugins.UserInfoClaimsPlugin}
*
* <li>
* The {@code getUserInfo} method
* populates scope values and sets the resource owner ID to return.
* </li>
*
*/
public class CustomUserInfoClaimsPlugin implements UserInfoClaimsPlugin {
@Override
public UserInfoClaims getUserInfo(ClientRegistration clientRegistration, AccessToken token, OAuth2Request request) {
Map<String, Object> response = mapScopes(token);
response.put("sub", token.getResourceOwnerId());
UserInfoClaims userInfoClaims = new UserInfoClaims(response, null);
return userInfoClaims;
}
/**
* Set read and write permissions according to scope.
*
* @param token The access token presented for validation.
* @return The map of read and write permissions,
* with permissions set to {@code true} or {@code false},
* as appropriate.
*/
private Map<String, Object> mapScopes(AccessToken token) {
Set<String> scopes = token.getScope();
Map<String, Object> map = new HashMap<String, Object>();
final String[] permissions = {"read", "write"};
for (String scope : permissions) {
if (scopes.contains(scope)) {
map.put(scope, true);
} else {
map.put(scope, false);
}
}
return map;
}
}
Custom user info claim examples
Refer to the following sections for example use cases:
If you are using the Ping Identity Platform, you can add a |
Add a custom claim to the profile scope
Complete the following steps to implement an example user info claims script that adds a custom claim to the profile scope:
This example adds the custom claim to the access token and uses the /oauth2/userinfo endpoint to inspect the custom claim values.
Configure the user info claims script
This task describes how to modify the default script to map a custom claim.
To create a new script instead, refer to Manage scripts (UI), and reference the new script name when you configure the provider.
-
In the AM admin UI, go to Realms > Realm Name > Scripts, and click OIDC Claims Script.
-
In the Script field:
-
Groovy
-
JavaScript
-
Add a new claim to the script. As a simple example, insert
myTestName
after thename
claim in theclaimAttributes
section as follows:claimAttributes = [ "email": userProfileClaimResolver.curry("mail"), ... "name": userProfileClaimResolver.curry("cn"), "myTestName": userProfileClaimResolver.curry("cn") ]
-
Add the new claim to the
profile
scope in the claims map:scopeClaimsMap = [ "email": [ "email" ], ... "profile": [ "given_name", "zoneinfo", "family_name", "locale", "name", "myTestName" ]
-
Add the new
myTestName
claim to theprofile
scope in theutils.setScopeClaimsMap
section:utils.setScopeClaimsMap({ profile: [ 'name', 'family_name', 'given_name', 'zoneinfo', 'locale', 'myTestName' ], email: ['email'],
-
Add the new claim to the script. For example, insert
myTestName
after thephone_number
claim in theutils.setClaimResolvers
section as follows:utils.setClaimResolvers({ ... phone_number: utils.getUserProfileClaimResolver('telephonenumber'), myTestName: utils.getUserProfileClaimResolver('cn') });
-
-
Save your changes.
The default user info claims script is now amended to retrieve a custom claim for the profile
scope.
Configure AM to use the user info claims script
Perform this task to set up an OAuth2 provider to use your custom script.
-
Configure the provider and ensure the following properties are set:
-
OIDC Claims Plugin Type to
SCRIPTED
. -
OIDC Claims Script to
OIDC Claims Script
.
If you created a new script rather than editing the default, reference the new script name here.
-
-
Save your changes.
Create an OAuth2 client for authorization
Create a public OAuth 2.0 client to use in the authorization request.
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.
-
Enter the following values:
-
Client ID:
myClient
-
Client secret:
mySecret
-
Redirection URIs:
https://www.example.com:443/callback
-
Scope(s):
openid
profile
-
-
Click Create.
-
In the Core tab, set Client type to
Public
. -
In the Advanced tab, set the following values:
-
Response Types:
token id_token
-
Grant Types:
Implicit
-
Token Endpoint Authentication Method:
none
-
-
Save your changes.
AM is now prepared for you to try this sample user info claims script.
Try the custom user info claims plugin script
To try your custom script, use the Implicit grant flow as demonstrated in the following steps.
-
Log in to AM as the
demo
user, for example:$ curl \ --request POST \ --header "Content-Type: application/json" \ --header "X-OpenAM-Username: demo" \ --header "X-OpenAM-Password: Ch4ng31t" \ --header "Accept-API-Version: resource=2.0, protocol=1.0" \ 'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate' { "tokenId":"AQIC5wM…TU3OQ*", "successUrl":"/openam/console", "realm":"/alpha" }
Copy the SSO token value returned as
tokenId
in the output. You’ll need this value in the next step. -
Invoke the authorization server’s /oauth2/authorize endpoint specifying the SSO token value in a cookie, and the following parameters as a minimum:
-
client_id=
myClient
-
response_type=
token id_token
-
scope=
openid profile
-
nonce=your nonce value
-
redirect_uri=
https://www.example.com:443/callback
-
decision=
allow
-
csrf=SSO-token
For example:
$ curl --dump-header - \ --cookie "iPlanetDirectoryPro=AQIC5wM…TU3OQ*" \ --request POST \ --data "client_id=myClient" \ --data "response_type=token id_token" \ --data "scope=openid profile" \ --data "state=123abc" \ --data "nonce=abc123" \ --data "decision=allow" \ --data "csrf=AQIC5wM…TU3OQ*" \ --data "redirect_uri=https://www.example.com:443/callback" \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize" HTTP/1.1 302 X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff Cache-Control: no-store Location: https://www.example.com:443/callback#access_token=az91IvnIQ-uP3Eqw5QqaXXY_DCo&id_token=eyJ0eXA…7QdQpg&state=123abc&token_type=Bearer&expires_in=3599 Pragma: no-cache Set-Cookie: OAUTH_REQUEST_ATTRIBUTES=DELETED; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/; HttpOnly Content-Length: 0 Date: Mon, 01 Jul 2024 14:10:09 GMT
Copy the value of the
access_token
appended to the redirection URI in the response. You’ll need this value in the next step. -
-
Call the /oauth2/userinfo endpoint to inspect the custom claim values, including the access token obtained from the previous request.
For example:
$ curl \ --request GET \ --header "Authorization: Bearer az91IvnIQ-uP3Eqw5QqaXXY_DCo" \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/userinfo" { "given_name":"Demo First Name", "family_name":"Demo Last Name", "name":"demo", "myTestName":"demo", "sub":"(usr!demo)", "subname":"demo" }
Verify the response contains the custom claim added by the script (
myTestName
in this example).
Add a custom claim to a custom scope
Complete the following steps to implement an example user info claims script that adds a custom claim to a custom scope:
This example adds the custom claim to the ID token and uses the /oauth2/idtokeninfo endpoint to inspect the custom claim values.
Configure the user info claims script
This task describes how to modify the default script to map a custom claim.
If you want the custom claim to use a custom attribute instead of an existing one, make sure you have added the custom user profile attribute first. |
To create a new script instead, refer to Manage scripts (UI), and reference the new script name when you configure the provider.
-
In the AM admin UI, go to Realms > Realm Name > Scripts, and click OIDC Claims Script.
-
In the Script field:
-
Groovy
-
JavaScript
-
Add a new claim to the script. As a simple example, insert
myCustomAttr
after thename
claim in theclaimAttributes
section as follows:claimAttributes = [ "email": userProfileClaimResolver.curry("mail"), ... "name": userProfileClaimResolver.curry("cn"), "myCustomAttr": userProfileClaimResolver.curry("employeenumber") ]
-
Add the new claim to a new
custom
scope in the claims map:scopeClaimsMap = [ "email": [ "email" ], ... "profile": [ "given_name", "zoneinfo", "family_name", "locale", "name" ], "custom": [ "myCustomAttr" ]
-
Add the new
myCustomAttr
claim to a newcustom
scope in theutils.setScopeClaimsMap
section:utils.setScopeClaimsMap({ ... phone: ['phone_number'], custom: ['myCustomAttr']
-
Add the new claim to the script. For example, insert
myCustomAttr
after thephone_number
claim in theutils.setClaimResolvers
section as follows:utils.setClaimResolvers({ ... phone_number: utils.getUserProfileClaimResolver('telephonenumber'), myCustomAttr: utils.getUserProfileClaimResolver('employeenumber') });
-
-
Save your changes.
The default user info claims script is now amended to retrieve a custom claim for the custom
scope.
Configure AM to use the user info claims script
Perform this task to set up an OAuth2 provider to use your custom script.
-
Configure the provider and ensure the following properties are set:
-
OIDC Claims Plugin Type to
SCRIPTED
. -
OIDC Claims Script to
OIDC Claims Script
.
If you created a new script rather than editing the default, reference the new script name here.
-
-
Save your changes.
Configure the provider to return claims in the ID token
Perform this task to configure the OAuth2 provider to always return scope-derived claims in the ID token.
This option is disabled by default because of the security concerns of returning claims that may contain sensitive user information. Learn more in Request claims in ID tokens. |
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
Select Always Return Claims in ID Tokens.
-
Save your changes.
Create an OAuth2 client for authorization
Create a public OAuth 2.0 client to use in the authorization request.
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.
-
Enter the following values:
-
Client ID:
myClient
-
Client secret:
mySecret
-
Redirection URIs:
https://www.example.com:443/callback
-
Scope(s):
openid
profile
custom
-
-
Click Create.
-
In the Core tab, set Client type to
Public
. -
In the Advanced tab, set the following values:
-
Response Types:
token id_token
-
Grant Types:
Implicit
-
Token Endpoint Authentication Method:
none
-
-
Save your changes.
AM is now prepared for you to try this sample user info claims script.
Try the custom user info claims plugin script
To try your custom script, use the Implicit grant flow as demonstrated in the following steps.
-
Log in to AM as the
demo
user, for example:$ curl \ --request POST \ --header "Content-Type: application/json" \ --header "X-OpenAM-Username: demo" \ --header "X-OpenAM-Password: Ch4ng31t" \ --header "Accept-API-Version: resource=2.0, protocol=1.0" \ 'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate' { "tokenId":"AQIC5wM…TU3OQ*", "successUrl":"/openam/console", "realm":"/alpha" }
Copy the SSO token value returned as
tokenId
in the output. You’ll need this value in the next step. -
Invoke the authorization server’s /oauth2/authorize endpoint specifying the SSO token value in a cookie, and the following parameters as a minimum:
-
client_id=
myClient
-
response_type=
token id_token
-
scope=
openid profile custom
-
nonce=your nonce value
-
redirect_uri=
https://www.example.com:443/callback
-
decision=
allow
-
csrf=SSO-token
For example:
$ curl --dump-header - \ --cookie "iPlanetDirectoryPro=AQIC5wM…TU3OQ*" \ --request POST \ --data "client_id=myClient" \ --data "response_type=token id_token" \ --data "scope=openid profile custom" \ --data "state=123abc" \ --data "nonce=abc123" \ --data "decision=allow" \ --data "csrf=AQIC5wM…TU3OQ*" \ --data "redirect_uri=https://www.example.com:443/callback" \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize" HTTP/1.1 302 X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff Cache-Control: no-store Location: https://www.example.com:443/callback#access_token=az91IvnIQ-uP3Eqw5QqaXXY_DCo&id_token=eyJ0eXA…7QdQpg&state=123abc&token_type=Bearer&expires_in=3599 Pragma: no-cache Set-Cookie: OAUTH_REQUEST_ATTRIBUTES=DELETED; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/; HttpOnly Content-Length: 0 Date: Mon, 01 Jul 2024 14:10:09 GMT
Copy the value of the
id_token
appended to the redirection URI in the response. You’ll need this value in the next step. -
-
Call the /oauth2/idtokeninfo endpoint to inspect the custom claim values, including the ID token obtained from the previous request.
For example:
$ curl \ --request POST \ --user myClient:mySecret \ --data 'id_token=eyJ0eXA…7QdQpg' \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/idtokeninfo" { "at_hash":"PZg5xZsIlFtRSfg8MAWhWg", "sub":"(usr!demo)", "auditTrackingId":"2e5c7611-4a61-4001-8739-f714d43e9da2-881454", "subname":"demo", "iss":"https://openam.example.com:8443/openam/oauth2", "tokenName":"id_token", "given_name":"Demo First Name", "nonce":"abc123", "sid":"+buKyDp+Fbc0/Rkd0OqsfdKy7ZY0nWvcsEetikX+eTc=", "myCustomAttr":"1234", "aud":"myClient", "acr":"0", "org.forgerock.openidconnect.ops":"gkQOcZ1F3ZFdYPd6TiGIgr6scH0", "s_hash":"bKE9UspwyIPg8LsQHkJaiQ", "azp":"myClient", "auth_time":1676360741, "name":"demo", "realm":"/alpha", "exp":1676364398, "tokenType":"JWTToken", "iat":1676360798, "family_name":"Demo Last Name" }
Verify the response contains the custom claim added by the script (
myCustomAttr
in this example).
Add a session property claim to the profile scope
Complete the following steps to implement an example user info claims script that adds a session property claim to the profile scope:
This example adds SSO session details to the ID token and uses the /oauth2/idtokeninfo endpoint to inspect the session property claim values.
These steps add the For a list of the default session properties, refer to Session properties. |
Configure the user info claims script
This task describes how to modify the default script to map a session property claim.
To create a new script instead, refer to Manage scripts (UI), and reference the new script name when you configure the provider.
-
In the AM admin UI, go to Realms > Realm Name > Scripts, and click OIDC Claims Script.
-
In the Script field:
-
Groovy
-
JavaScript
-
Add a new claim to the script. For example, insert
AuthLevel
after thename
claim in theclaimAttributes
section as follows:claimAttributes = [ "email": userProfileClaimResolver.curry("mail"), ... "name": userProfileClaimResolver.curry("cn"), "AuthLevel": { claim, identity -> [ (claim.getName()): session.getProperty("AuthLevel") ] } ]
-
Add the new claim to the
profile
scope in the claims map:scopeClaimsMap = [ "email": [ "email" ], ... "profile": [ "given_name", "zoneinfo", "family_name", "locale", "name", "AuthLevel" ]
-
Add the new
AuthLevel
claim to theprofile
scope in theutils.setScopeClaimsMap
section:utils.setScopeClaimsMap({ profile: [ 'name', 'family_name', 'given_name', 'zoneinfo', 'locale', 'AuthLevel' ], email: ['email'],
-
Add the new claim to the script. For example, insert
AuthLevel
after thephone_number
claim in theutils.setClaimResolvers
section as follows:utils.setClaimResolvers({ ... phone_number: utils.getUserProfileClaimResolver('telephonenumber'), AuthLevel: function () { return session.getProperty('AuthLevel'); } });
-
-
Save your changes.
The default user info claims script is now amended to retrieve a session property claim for the profile
scope.
Allowlist the session property
Provide access to the session property to allow it to be output in the ID token.
-
In the AM admin UI, go to Realms > Realm Name > Services > Session Property Whitelist Service.
-
Add
AuthLevel
to the Allowlisted Session Property Names field. -
Save your changes.
Configure AM to use the user info claims script
Perform this task to set up an OAuth2 provider to use your custom script.
-
Configure the provider and ensure the following properties are set:
-
OIDC Claims Plugin Type to
SCRIPTED
. -
OIDC Claims Script to
OIDC Claims Script
.
If you created a new script rather than editing the default, reference the new script name here.
-
-
Save your changes.
Configure the provider to return claims in the ID token
Perform this task to configure the OAuth2 provider to always return scope-derived claims in the ID token.
This option is disabled by default because of the security concerns of returning claims that may contain sensitive user information. Learn more in Request claims in ID tokens. |
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
Select Always Return Claims in ID Tokens.
-
Save your changes.
Create an OAuth2 client for authorization
Create a public OAuth 2.0 client to use in the authorization request.
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.
-
Enter the following values:
-
Client ID:
myClient
-
Client secret:
mySecret
-
Redirection URIs:
https://www.example.com:443/callback
-
Scope(s):
openid
profile
-
-
Click Create.
-
In the Core tab, set Client type to
Public
. -
In the Advanced tab, set the following values:
-
Response Types:
token id_token
-
Grant Types:
Implicit
-
Token Endpoint Authentication Method:
none
-
-
Save your changes.
AM is now prepared for you to try this sample user info claims script.
Try the custom user info claims plugin script
To try your custom script, use the Implicit grant flow as demonstrated in the following steps.
-
Log in to AM as the
demo
user, for example:$ curl \ --request POST \ --header "Content-Type: application/json" \ --header "X-OpenAM-Username: demo" \ --header "X-OpenAM-Password: Ch4ng31t" \ --header "Accept-API-Version: resource=2.0, protocol=1.0" \ 'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate' { "tokenId":"AQIC5wM…TU3OQ*", "successUrl":"/openam/console", "realm":"/alpha" }
Copy the SSO token value returned as
tokenId
in the output. You’ll need this value in the next step. -
Invoke the authorization server’s /oauth2/authorize endpoint specifying the SSO token value in a cookie, and the following parameters as a minimum:
-
client_id=
myClient
-
response_type=
token id_token
-
scope=
openid profile
-
nonce=your nonce value
-
redirect_uri=
https://www.example.com:443/callback
-
decision=
allow
-
csrf=SSO-token
For example:
$ curl --dump-header - \ --cookie "iPlanetDirectoryPro=AQIC5wM…TU3OQ*" \ --request POST \ --data "client_id=myClient" \ --data "response_type=token id_token" \ --data "scope=openid profile" \ --data "state=123abc" \ --data "nonce=abc123" \ --data "decision=allow" \ --data "csrf=AQIC5wM…TU3OQ*" \ --data "redirect_uri=https://www.example.com:443/callback" \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize" HTTP/1.1 302 X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff Cache-Control: no-store Location: https://www.example.com:443/callback#access_token=az91IvnIQ-uP3Eqw5QqaXXY_DCo&id_token=eyJ0eXA…7QdQpg&state=123abc&token_type=Bearer&expires_in=3599 Pragma: no-cache Set-Cookie: OAUTH_REQUEST_ATTRIBUTES=DELETED; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/; HttpOnly Content-Length: 0 Date: Mon, 01 Jul 2024 14:10:09 GMT
Copy the value of the
id_token
appended to the redirection URI in the response. You’ll need this value in the next step. -
-
Call the /oauth2/idtokeninfo endpoint to inspect the session property claim values, including the ID token obtained from the previous request.
For example:
$ curl \ --request POST \ --user myClient:mySecret \ --data 'id_token=eyJ0eXA…7QdQpg' \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/idtokeninfo" { "at_hash":"PZg5xZsIlFtRSfg8MAWhWg", "sub":"(usr!demo)", "auditTrackingId":"2e5c7611-4a61-4001-8739-f714d43e9da2-881454", "subname":"demo", "iss":"https://openam.example.com:8443/openam/oauth2", "tokenName":"id_token", "given_name":"Demo First Name", "nonce":"abc123", "sid":"+buKyDp+Fbc0/Rkd0OqsfdKy7ZY0nWvcsEetikX+eTc=", "AuthLevel":"0", "aud":"myClient", "acr":"0", "org.forgerock.openidconnect.ops":"gkQOcZ1F3ZFdYPd6TiGIgr6scH0", "s_hash":"bKE9UspwyIPg8LsQHkJaiQ", "azp":"myClient", "auth_time":1676360741, "name":"demo", "realm":"/alpha", "exp":1676364398, "tokenType":"JWTToken", "iat":1676360798, "family_name":"Demo Last Name" }
Verify the response contains the session property claim added by the script (
AuthLevel
in this example).
Add a groups claim to the profile scope
Complete the following steps to implement an example user info claims script that adds a groups claim to the profile scope:
This example adds group membership details to the ID token and uses the /oauth2/idtokeninfo endpoint to inspect the groups claim values.
Configure the user info claims script
This task describes how to modify the default script to map a groups claim.
To create a new script instead, refer to Manage scripts (UI), and reference the new script name when you configure the provider.
-
In the AM admin UI, go to Realms > Realm Name > Scripts, and click OIDC Claims Script.
-
In the Script field:
-
Groovy
-
JavaScript
-
Import the
com.sun.identity.idm.IdType
class into the script:import com.iplanet.sso.SSOException … import org.forgerock.openidconnect.Claim import com.sun.identity.idm.IdType
-
Add a new claim to the script. For example, insert
groups
after thename
claim in theclaimAttributes
section as follows:claimAttributes = [ "email": userProfileClaimResolver.curry("mail"), ... "name": userProfileClaimResolver.curry("cn"), "groups": { claim, identity -> [ "groups" : identity.getMemberships(IdType.GROUP).collect { group -> group.name }]} ]
You can reformat the claims value returned. For example, replace { group → group.name }
in the previous code sample with{ group → 'ROLE_' + group.name }
to return the group name with aROLE_
prefix. -
Add the new claim to the
profile
scope in the claims map:scopeClaimsMap = [ "email": [ "email" ], ... "profile": [ "given_name", "zoneinfo", "family_name", "locale", "name", "groups" ]
-
Add the new
groups
claim to theprofile
scope in theutils.setScopeClaimsMap
section:utils.setScopeClaimsMap({ profile: [ 'name', 'family_name', 'given_name', 'zoneinfo', 'locale', 'groups' ], email: ['email'],
-
Add the new claim to the script. For example, insert
groups
after thephone_number
claim in theutils.setClaimResolvers
section as follows:utils.setClaimResolvers({ ... phone_number: utils.getUserProfileClaimResolver('telephonenumber'), groups: function() { var fr = JavaImporter( com.sun.identity.idm.IdType ); var groups = []; identity.getMemberships(fr.IdType.GROUP).toArray().forEach(function(group) { groups.push(group.getAttribute('cn').toArray()[0]); }); return groups; } });
-
-
Save your changes.
The default user info claims script is now amended to retrieve a groups claim for the profile
scope.
Allowlist the Java class
Allow the script to access the Java class you imported.
-
In the AM admin UI, go to Configure > Global Services > Scripting > Secondary Configurations > OIDC_CLAIMS > Secondary Configurations > engineConfiguration.
-
Add
com.sun.identity.idm.IdType
to the Java class whitelist field. -
Save your changes.
Configure AM to use the user info claims script
Perform this task to set up an OAuth2 provider to use your custom script.
-
Configure the provider and ensure the following properties are set:
-
OIDC Claims Plugin Type to
SCRIPTED
. -
OIDC Claims Script to
OIDC Claims Script
.
If you created a new script rather than editing the default, reference the new script name here.
-
-
Save your changes.
Configure the provider to return claims in the ID token
Perform this task to configure the OAuth2 provider to always return scope-derived claims in the ID token.
This option is disabled by default because of the security concerns of returning claims that may contain sensitive user information. Learn more in Request claims in ID tokens. |
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
Select Always Return Claims in ID Tokens.
-
Save your changes.
Create an OAuth2 client for authorization
Create a public OAuth 2.0 client to use in the authorization request.
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.
-
Enter the following values:
-
Client ID:
myClient
-
Client secret:
mySecret
-
Redirection URIs:
https://www.example.com:443/callback
-
Scope(s):
openid
profile
-
-
Click Create.
-
In the Core tab, set Client type to
Public
. -
In the Advanced tab, set the following values:
-
Response Types:
token id_token
-
Grant Types:
Implicit
-
Token Endpoint Authentication Method:
none
-
-
Save your changes.
AM is now prepared for you to try this sample user info claims script.
Try the custom user info claims plugin script
To try your custom script, use the Implicit grant flow as demonstrated in the following steps.
-
Log in to AM as the
demo
user, for example:$ curl \ --request POST \ --header "Content-Type: application/json" \ --header "X-OpenAM-Username: demo" \ --header "X-OpenAM-Password: Ch4ng31t" \ --header "Accept-API-Version: resource=2.0, protocol=1.0" \ 'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate' { "tokenId":"AQIC5wM…TU3OQ*", "successUrl":"/openam/console", "realm":"/alpha" }
Copy the SSO token value returned as
tokenId
in the output. You’ll need this value in the next step. -
Invoke the authorization server’s /oauth2/authorize endpoint specifying the SSO token value in a cookie, and the following parameters as a minimum:
-
client_id=
myClient
-
response_type=
token id_token
-
scope=
openid profile
-
nonce=your nonce value
-
redirect_uri=
https://www.example.com:443/callback
-
decision=
allow
-
csrf=SSO-token
For example:
$ curl --dump-header - \ --cookie "iPlanetDirectoryPro=AQIC5wM…TU3OQ*" \ --request POST \ --data "client_id=myClient" \ --data "response_type=token id_token" \ --data "scope=openid profile" \ --data "state=123abc" \ --data "nonce=abc123" \ --data "decision=allow" \ --data "csrf=AQIC5wM…TU3OQ*" \ --data "redirect_uri=https://www.example.com:443/callback" \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize" HTTP/1.1 302 X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff Cache-Control: no-store Location: https://www.example.com:443/callback#access_token=az91IvnIQ-uP3Eqw5QqaXXY_DCo&id_token=eyJ0eXA…7QdQpg&state=123abc&token_type=Bearer&expires_in=3599 Pragma: no-cache Set-Cookie: OAUTH_REQUEST_ATTRIBUTES=DELETED; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/; HttpOnly Content-Length: 0 Date: Mon, 01 Jul 2024 14:10:09 GMT
Copy the value of the
id_token
appended to the redirection URI in the response. You’ll need this value in the next step. -
-
Call the /oauth2/idtokeninfo endpoint to inspect the groups claim values, including the ID token obtained from the previous request.
For example:
$ curl \ --request POST \ --user myClient:mySecret \ --data 'id_token=eyJ0eXA…7QdQpg' \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/idtokeninfo" { "at_hash":"PZg5xZsIlFtRSfg8MAWhWg", "sub":"(usr!demo)", "auditTrackingId":"2e5c7611-4a61-4001-8739-f714d43e9da2-881454", "subname":"demo", "iss":"https://openam.example.com:8443/openam/oauth2", "tokenName":"id_token", "groups": [ "supervisors", "employees" ], "given_name":"Demo First Name", "nonce":"abc123", "sid":"+buKyDp+Fbc0/Rkd0OqsfdKy7ZY0nWvcsEetikX+eTc=", "aud":"myClient", "acr":"0", "org.forgerock.openidconnect.ops":"gkQOcZ1F3ZFdYPd6TiGIgr6scH0", "s_hash":"bKE9UspwyIPg8LsQHkJaiQ", "azp":"myClient", "auth_time":1676360741, "name":"demo", "realm":"/alpha", "exp":1676364398, "tokenType":"JWTToken", "iat":1676360798, "family_name":"Demo Last Name" }
Verify the response contains the groups claim added by the script (
groups
in this example).
Override the audience and issuer claims
Complete the following steps to implement an example user info claims script that overrides the aud
(audience) and iss
(issuer) claims:
This example overrides the aud
and iss
claims in the ID token and uses the /oauth2/idtokeninfo endpoint to inspect the overridden claims.
These steps override the For information about the core OIDC claims, refer to the ID Token data structure. |
Configure the user info claims script
This task describes how to modify the default script to override the aud
and iss
claims.
To create a new script instead, refer to Manage scripts (UI), and reference the new script name when you configure the provider.
-
In the AM admin UI, go to Realms > Realm Name > Scripts, and click OIDC Claims Script.
-
In the Script field:
-
Groovy
-
JavaScript
-
Add the claim override details after the existing
computedClaims
line. You can specify overrides as a string or an array. For example, add aniss
override as a string:computedClaims = claimsToResolve.collectEntries() { claim -> result = computeClaim(claim) } computedClaims.put("iss", "https://example.com")
-
Then add an
aud
override as an array:def audClaim = ["myClient","testClient"]; computedClaims.put("aud", audClaim)
-
Add the claim override details before the
return computedClaims;
line. You can specify overrides as a string or an array. For example, add aniss
override as a string:computedClaims.put("iss", "https://example.com") return computedClaims;
-
Then add an
aud
override as an array:var audClaim = ["myClient","testClient"]; computedClaims.put("aud", audClaim)
The
aud
override values you specify must correspond to registered clients; otherwise you’ll see an error when you inspect the claim values.Replace
testClient
in the script above with the ID of another registered OAuth2 client, or create a temporary OAuth2 client calledtestClient
for testing purposes. -
-
Save your changes.
The default user info claims script is now amended to override claims.
Configure AM to use the user info claims script
Perform this task to set up an OAuth2 provider to use your custom script.
-
Configure the provider and ensure the following properties are set:
-
OIDC Claims Plugin Type to
SCRIPTED
. -
OIDC Claims Script to
OIDC Claims Script
.
If you created a new script rather than editing the default, reference the new script name here.
-
-
Save your changes.
Configure the provider to return claims in the ID token
Perform this task to configure the OAuth2 provider to always return scope-derived claims in the ID token.
This option is disabled by default because of the security concerns of returning claims that may contain sensitive user information. Learn more in Request claims in ID tokens. |
-
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect.
-
Select Always Return Claims in ID Tokens.
-
Save your changes.
Create an OAuth2 client for authorization
Create a public OAuth 2.0 client to use in the authorization request.
-
In the AM admin UI, go to Realms > Realm Name > Applications > OAuth 2.0 > Clients, and click Add Client.
-
Enter the following values:
-
Client ID:
myClient
-
Client secret:
mySecret
-
Redirection URIs:
https://www.example.com:443/callback
-
Scope(s):
openid
profile
-
-
Click Create.
-
In the Core tab, set Client type to
Public
. -
In the Advanced tab, set the following values:
-
Response Types:
token id_token
-
Grant Types:
Implicit
-
Token Endpoint Authentication Method:
none
-
-
In the OAuth2 Provider Overrides tab, select Enable OAuth2 Provider Overrides.
-
Enter
aud
iss
in the Overrideable Id_Token Claims field.You can specify the claims to override in the OAuth2 Provider instead. The Overrideable Id_Token Claims field is on the OpenID Connect tab in the provider. -
Save your changes.
AM is now prepared for you to try this sample user info claims script.
Try the custom user info claims plugin script
To try your custom script, use the Implicit grant flow as demonstrated in the following steps.
-
Log in to AM as the
demo
user, for example:$ curl \ --request POST \ --header "Content-Type: application/json" \ --header "X-OpenAM-Username: demo" \ --header "X-OpenAM-Password: Ch4ng31t" \ --header "Accept-API-Version: resource=2.0, protocol=1.0" \ 'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate' { "tokenId":"AQIC5wM…TU3OQ*", "successUrl":"/openam/console", "realm":"/alpha" }
Copy the SSO token value returned as
tokenId
in the output. You’ll need this value in the next step. -
Invoke the authorization server’s /oauth2/authorize endpoint specifying the SSO token value in a cookie, and the following parameters as a minimum:
-
client_id=
myClient
-
response_type=
token id_token
-
scope=
openid profile
-
nonce=your nonce value
-
redirect_uri=
https://www.example.com:443/callback
-
decision=
allow
-
csrf=SSO-token
For example:
$ curl --dump-header - \ --cookie "iPlanetDirectoryPro=AQIC5wM…TU3OQ*" \ --request POST \ --data "client_id=myClient" \ --data "response_type=token id_token" \ --data "scope=openid profile" \ --data "state=123abc" \ --data "nonce=abc123" \ --data "decision=allow" \ --data "csrf=AQIC5wM…TU3OQ*" \ --data "redirect_uri=https://www.example.com:443/callback" \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize" HTTP/1.1 302 X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff Cache-Control: no-store Location: https://www.example.com:443/callback#access_token=az91IvnIQ-uP3Eqw5QqaXXY_DCo&id_token=eyJ0eXA…7QdQpg&state=123abc&token_type=Bearer&expires_in=3599 Pragma: no-cache Set-Cookie: OAUTH_REQUEST_ATTRIBUTES=DELETED; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/; HttpOnly Content-Length: 0 Date: Mon, 01 Jul 2024 14:10:09 GMT
Copy the value of the
id_token
appended to the redirection URI in the response. You’ll need this value in the next step. -
-
Call the /oauth2/idtokeninfo endpoint to inspect the overridden claims, including the ID token obtained from the previous request.
For example:
$ curl \ --request POST \ --user myClient:mySecret \ --data 'id_token=eyJ0eXA…7QdQpg' \ "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/idtokeninfo" { "at_hash":"PZg5xZsIlFtRSfg8MAWhWg", "sub":"(usr!demo)", "auditTrackingId":"2e5c7611-4a61-4001-8739-f714d43e9da2-881454", "subname":"demo", "iss":"https://example.com", "tokenName":"id_token", "given_name":"Demo First Name", "nonce":"abc123", "sid":"+buKyDp+Fbc0/Rkd0OqsfdKy7ZY0nWvcsEetikX+eTc=", "aud": [ "myClient", "testClient" ], "acr":"0", "org.forgerock.openidconnect.ops":"gkQOcZ1F3ZFdYPd6TiGIgr6scH0", "s_hash":"bKE9UspwyIPg8LsQHkJaiQ", "azp":"myClient", "auth_time":1676360741, "name":"demo", "realm":"/alpha", "exp":1676364398, "tokenType":"JWTToken", "iat":1676360798, "family_name":"Demo Last Name" }
Verify the response contains the overridden
iss
andaud
values.
OIDC user info claims scripting API
The following properties are available to user info claims scripts.
Binding | Information | ||
---|---|---|---|
|
A map of the claims the server provides by default. For example:
|
||
|
An array of string values from the For details, refer to Claims Languages and Scripts in the OpenID Connect Core 1.0 specification. |
||
|
The default OpenID Connect 1.0 claims provided by AM. |
||
|
A read-only map of the following client properties. Only present if AM identified the client specified in the request.
|
||
|
An HTTP client for making external HTTP requests. |
||
|
Represents an identity that AM can access. For details, refer to AMIdentity. |
||
The logger instance for the script. Logger names use the format Refer to Debug logging. |
|||
|
A map of requested claims.
This is empty unless the request includes the To configure AM in the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider > Advanced OpenID Connect. Enable Enable "claims_parameter_supported" and save your change. For details about the Example:
|
||
|
A list of the requested claims objects.
This is empty unless the request includes the A claim with a single value means the script should return only that value. |
||
|
A read-only map of the following request properties.
|
||
|
The set of scope strings in the client request. |
||
|
The display name of the script. |
||
|
The user’s session object. For details, refer to SSOToken. |