---
title: OIDC claims
description: 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.
component: pingam
version: 8.1
page_id: pingam:am-oauth2:plugins-user-info-claims
canonical_url: https://docs.pingidentity.com/pingam/8.1/am-oauth2/plugins-user-info-claims.html
keywords: ["OAuth 2.0", "OpenID Connect (OIDC)", "Customizations", "Plugins", "Authorization", "Java", "Scripting"]
page_aliases: ["oauth2-guide:plugins-user-info-claims.adoc"]
section_ids:
  examples_using_legacy_scripts: Examples using legacy scripts
  example-add-custom-claim-profile-scope: Add a custom claim to the profile scope
  config-oidc-plugin: Create the script
  configure-provider-claims-id-token: Configure the provider
  create-oidc-client: Create a client application
  try-oidc-plugin: Try the script
  example-add-custom-claim-custom-scope: Add a custom claim to a custom scope
  config-oidc-plugin-custom: Create the script
  configure-provider-claims-id-token-custom: Configure the provider
  create-oidc-client-custom: Create a client application
  try-oidc-plugin-custom: Try the script
  example-add-session-claim-profile-scope: Add a session property claim to the profile scope
  config-oidc-plugin-session: Create the script
  allowlist-session-property: Allowlist the session property
  configure-provider-claims-id-token-session: Configure the provider
  create-oidc-client-session: Create a client application
  try-oidc-plugin-session: Try the script
  example-add-group-claim-profile-scope: Add a groups claim to the profile scope
  config-oidc-plugin-groups: Create the script
  allowlist-java-class: Allowlist the Java class
  configure-provider-claims-id-token-groups: Configure the provider
  create-oidc-client-groups: Create a client application
  try-oidc-plugin-groups: Try the script
  example-override-issuer-audience: Override the audience and issuer claims
  config-oidc-plugin-override: Create the script
  configure-provider-claims-id-token-override: Configure the provider
  create-oidc-client-override: Create a client application
  try-oidc-plugin-override: Try the script
  example-oidc-claims-nextgen: Example using a next-generation script
  config-oidc-plugin-ng: Create the OIDC claims script
  configure-provider-ng: Configure the provider
  create-oidc-client-ng: Create a client application
  try-oidc-plugin-ng: Try the script
---

# OIDC 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.

* Sample scripts

  * [OIDC Claims Script](../am-scripting/sample-scripts.html#oidc-claims-extension-js) (Legacy JavaScript)

  * [OIDC Claims Script](../am-scripting/sample-scripts.html#oidc-claims-extension-groovy) (Groovy)

* Script bindings

  * [Common bindings](../am-scripting/script-bindings.html)

  * [OIDC claims scripting API](../am-scripting/user-info-claims-api.html)

* Java interface

  `org.forgerock.oauth2.core.plugins.UserInfoClaimsPlugin`

  > **Collapse: Sample Java code**
  >
  > ```java
  > /*
  >  * Copyright 2021-2025 Ping Identity Corporation. All Rights Reserved
  >  *
  >  * This code is to be used exclusively in connection with Ping Identity
  >  * Corporation software or services. Ping Identity Corporation only offers
  >  * such software or services to legal entities who have entered into a
  >  * binding license agreement with Ping Identity Corporation.
  >  */
  >
  > 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;
  >     }
  > }
  > ```

## Examples using legacy scripts

Refer to the following sections for example use cases:

* [Add a custom claim to the profile scope](#example-add-custom-claim-profile-scope)

* [Add a custom claim to a custom scope](#example-add-custom-claim-custom-scope)

* [Add a session property claim to the profile scope](#example-add-session-claim-profile-scope)

* [Add a groups claim to the profile scope](#example-add-group-claim-profile-scope)

* [Override the audience and issuer claims](#example-override-issuer-audience)

|   |                                                                                                                                                                                                                                                                                                                                                                                                                  |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | If you are using the Ping Advanced Identity Software, you can add a `post_logout_url` claim that redirects a user's browser to the URL specified in the claim, when that user signs out of the platform End User UI. For details, refer to [Redirect on signout](https://docs.pingidentity.com/platform/8.1/sample-setup/platform-ui.html#post-logout-url) in the Ping Advanced Identity Software documentation. |

### Add a custom claim to the profile scope

Complete the following steps to implement an example OIDC claims script that adds a custom claim to the profile scope:

1. [Create the script](#config-oidc-plugin)

2. [Configure the provider](#configure-provider-claims-id-token)

3. [Create a client application](#create-oidc-client)

4. [Try the script](#try-oidc-plugin)

This example adds the custom claim to the access token and uses the [/oauth2/userinfo](../am-oidc1/rest-api-oidc-userinfo-endpoint.html) endpoint to inspect the custom claim values.

#### Create the script

This task describes how to modify the default script to map a custom claim.

This example uses a legacy script. Find a next-generation example [here](#example-oidc-claims-nextgen).

1. In the AM admin UI, go to Realms > *realm name* > Scripts, and click OIDC Claims Script.

2. In the Script field:

   * Groovy

   * JavaScript

   - Add a new claim to the script. As a simple example, insert `myTestName` after the `name` claim in the `claimAttributes` section as follows:

     ```javascript
     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:

     ```javascript
     scopeClaimsMap = [
         "email": [ "email" ],
         ...
         "profile": [ "given_name", "zoneinfo", "family_name", "locale", "name", "myTestName" ]
     ```

   * Add the new `myTestName` claim to the `profile` scope in the `utils.setScopeClaimsMap` section:

     ```javascript
     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 the `phone_number` claim in the `utils.setClaimResolvers` section as follows:

     ```javascript
     utils.setClaimResolvers({
             ...
             phone_number: utils.getUserProfileClaimResolver('telephonenumber'),
             myTestName: utils.getUserProfileClaimResolver('cn')
         });
     ```

3. Save your changes.

The default OIDC claims script is now amended to retrieve a custom claim for the `profile` scope.

#### Configure the provider

Perform this task to set up an OAuth 2.0 provider to use your custom script.

1. [Configure the provider](customizing-oauth2-scopes.html#configure-scripted-oauth2-plugin) and make sure the following properties are set:

   * OIDC Claims Plugin Type to `SCRIPTED`.

   * OIDC Claims Script to the name of your custom script.

2. Save your changes.

#### Create a client application

Create a *public* OAuth 2.0 client to use in the authorization request.

1. In the AM admin UI, go to Realms > *realm name* > Applications > OAuth 2.0 > Clients, and click Add Client.

2. Enter the following values:

   * **Client ID**: `myClient`

   * **Client secret**: `mySecret`

   * **Redirection URIs**: `https://www.example.com:443/callback`

   * **Scope(s)**: `openid` `profile`

3. Click Create.

4. On the Core tab, set Client type to `Public`, and click Save.

5. On the Advanced tab, set the following values:

   * **Response Types**: `token id_token`

   * **Grant Types**: `Implicit`

   * **Token Endpoint Authentication Method**: `none`

6. Save your changes.

AM is now prepared for you to try this sample user info claims script.

### Try the script

To try your custom script, use the [Implicit grant](oauth2-implicit-grant.html) flow as demonstrated in the following steps.

1. Log in to AM as a test user, for example:

   ```bash
   $ curl \
   --request POST \
   --header "Content-Type: application/json" \
   --header "X-OpenAM-Username: bjensen" \
   --header "X-OpenAM-Password: Ch4ng31t" \
   --header "Accept-API-Version: resource=2.0, protocol=1.0" \
   'https://am.example.com:8443/am/json/realms/root/realms/alpha/authenticate'
   {
       "tokenId":"AQIC5wM…​TU3OQ*",
       "successUrl":"/am/console",
       "realm":"/alpha"
   }
   ```

   Copy the SSO token value returned as `tokenId` in the output. You'll need this value in the next step.

2. Invoke the authorization server's [/oauth2/authorize](oauth2-authorize-endpoint.html) 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:

   ```bash
   $ 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://am.example.com:8443/am/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.

3. Call the [/oauth2/userinfo](../am-oidc1/rest-api-oidc-userinfo-endpoint.html) endpoint to inspect the custom claim values, including the access token obtained from the previous request.

   For example:

   ```bash
   $ curl \
   --request GET \
   --header "Authorization: Bearer az91IvnIQ-uP3Eqw5QqaXXY_DCo" \
   "https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/userinfo"
   {
     "given_name":"Babs",
     "family_name":"Jensen",
     "name":"bjensen",
     "myTestName":"bjensen",
     "sub":"(usr!bjensen)",
     "subname":"bjensen"
   }
   ```

   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 OIDC claims script that adds a custom claim to a custom scope:

1. [Create the script](#config-oidc-plugin-custom)

2. [Configure the provider](#configure-provider-claims-id-token-custom)

3. [Create a client application](#create-oidc-client-custom)

4. [Try the script](#try-oidc-plugin-custom)

This example adds the custom claim to the ID token and uses the [/oauth2/idtokeninfo](../am-oidc1/rest-api-oidc-idtoken-validation.html) endpoint to inspect the custom claim values.

#### Create the 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](../setup/customizing-data-stores.html#sec-maint-datastore-customattr) first. |

This example uses a legacy script. Find a next-generation example [here](#example-oidc-claims-nextgen).

1. In the AM admin UI, go to Realms > *realm name* > Scripts, and click OIDC Claims Script.

2. In the Script field:

   * Groovy

   * JavaScript

   - Add a new claim to the script. As a simple example, insert `myCustomAttr` after the `name` claim in the `claimAttributes` section as follows:

     ```javascript
     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:

     ```javascript
     scopeClaimsMap = [
         "email": [ "email" ],
         ...
         "profile": [ "given_name", "zoneinfo", "family_name", "locale", "name" ],
         "custom": [ "myCustomAttr" ]
     ```

   * Add the new `myCustomAttr` claim to a new `custom` scope in the `utils.setScopeClaimsMap` section:

     ```javascript
     utils.setScopeClaimsMap({
             ...
             phone: ['phone_number'],
             custom: ['myCustomAttr']
     ```

   * Add the new claim to the script. For example, insert `myCustomAttr` after the `phone_number` claim in the `utils.setClaimResolvers` section as follows:

     ```javascript
     utils.setClaimResolvers({
             ...
             phone_number: utils.getUserProfileClaimResolver('telephonenumber'),
             myCustomAttr: utils.getUserProfileClaimResolver('employeenumber')
         });
     ```

3. Save your changes.

The default OIDC claims script is now amended to retrieve a custom claim for the `custom` scope.

#### Configure the provider

Perform this task to set up an OAuth 2.0 provider to use your custom script.

1. [Configure the provider](customizing-oauth2-scopes.html#configure-scripted-oauth2-plugin) and make sure the following properties are set:

   * OIDC Claims Plugin Type to `SCRIPTED`.

   * OIDC Claims Script to the name of your custom script.

2. Save your changes.

3. Switch to the Advanced OpenID Connect tab to always return scope-derived claims in the ID token.

4. Select Always Return Claims in ID Tokens.

   |   |                                                                                                                                                                                                                                                                          |
   | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
   |   | 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](../am-oidc1/understanding-openid-connect-scopes-and-claims.html#request-claims-tokens). |

5. Save your changes.

#### Create a client application

Create a *public* OAuth 2.0 client to use in the authorization request.

1. In the AM admin UI, go to Realms > *realm name* > Applications > OAuth 2.0 > Clients, and click Add Client.

2. Enter the following values:

   * **Client ID**: `myClient`

   * **Client secret**: `mySecret`

   * **Redirection URIs**: `https://www.example.com:443/callback`

   * **Scope(s)**: `openid` `profile` `custom`

3. Click Create.

4. On the Core tab, set Client type to `Public`, and click Save.

5. On the Advanced tab, set the following values:

   * **Response Types**: `token id_token`

   * **Grant Types**: `Implicit`

   * **Token Endpoint Authentication Method**: `none`

6. Save your changes.

AM is now prepared for you to try this sample OIDC claims script.

#### Try the script

To try your custom script, use the [Implicit grant](oauth2-implicit-grant.html) flow as demonstrated in the following steps.

1. Log in to AM as a test user, for example:

   ```bash
   $ curl \
   --request POST \
   --header "Content-Type: application/json" \
   --header "X-OpenAM-Username: bjensen" \
   --header "X-OpenAM-Password: Ch4ng31t" \
   --header "Accept-API-Version: resource=2.0, protocol=1.0" \
   'https://am.example.com:8443/am/json/realms/root/realms/alpha/authenticate'
   {
       "tokenId":"AQIC5wM…​TU3OQ*",
       "successUrl":"/am/console",
       "realm":"/alpha"
   }
   ```

   Copy the SSO token value returned as `tokenId` in the output. You'll need this value in the next step.

2. Invoke the authorization server's [/oauth2/authorize](oauth2-authorize-endpoint.html) 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:

   ```bash
   $ 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://am.example.com:8443/am/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.

3. Call the [/oauth2/idtokeninfo](../am-oidc1/rest-api-oidc-idtoken-validation.html) endpoint to inspect the custom claim values, including the ID token obtained from the previous request.

   For example:

   ```bash
   $ curl \
   --request POST \
   --user myClient:mySecret \
   --data 'id_token=eyJ0eXA…​7QdQpg' \
   "https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/idtokeninfo"
   {
     "at_hash":"PZg5xZsIlFtRSfg8MAWhWg",
     "sub":"(usr!bjensen)",
     "auditTrackingId":"2e5c7611-4a61-4001-8739-f714d43e9da2-881454",
     "subname":"bjensen",
     "iss":"https://am.example.com:8443/am/oauth2",
     "tokenName":"id_token",
     "given_name":"Babs",
     "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":"bjensen",
     "realm":"/alpha",
     "exp":1676364398,
     "tokenType":"JWTToken",
     "iat":1676360798,
     "family_name":"Jensen"
   }
   ```

   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 OIDC claims script that adds a session property claim to the profile scope:

1. [Create the script](#config-oidc-plugin-session)

2. [Allowlist the session property](#allowlist-session-property)

3. [Configure the provider](#configure-provider-claims-id-token-session)

4. [Create a client application](#create-oidc-client-session)

5. [Try the script](#try-oidc-plugin-session)

This example adds SSO session details to the ID token and uses the [/oauth2/idtokeninfo](../am-oidc1/rest-api-oidc-idtoken-validation.html) endpoint to inspect the session property claim values.

|   |                                                                                                                                                                                                                                                                                                                              |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | These steps add the `AuthLevel` session property, but the same steps apply to all session properties, including custom and protected properties (ones with an `am-protected` prefix).Find a list of the default session properties in [Session properties](../am-authentication/auth-tree-webhooks.html#session-properties). |

#### Create the script

This task describes how to modify the default script to map a session property claim.

This example uses a legacy script. Find a next-generation example [here](#example-oidc-claims-nextgen).

1. In the AM admin UI, go to Realms > *realm name* > Scripts, and click OIDC Claims Script.

2. In the Script field:

   * Groovy

   * JavaScript

   - Add a new claim to the script. For example, insert `AuthLevel` after the `name` claim in the `claimAttributes` section as follows:

     ```javascript
     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:

     ```javascript
     scopeClaimsMap = [
        "email": [ "email" ],
        ...
        "profile": [ "given_name", "zoneinfo", "family_name", "locale", "name", "AuthLevel" ]
     ```

   * Add the new `AuthLevel` claim to the `profile` scope in the `utils.setScopeClaimsMap` section:

     ```javascript
     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 the `phone_number` claim in the `utils.setClaimResolvers` section as follows:

     ```javascript
     utils.setClaimResolvers({
             ...
             phone_number: utils.getUserProfileClaimResolver('telephonenumber'),
             AuthLevel: function () {
                 return session.getProperty('AuthLevel');
             }

         });
     ```

3. Save your changes.

The default OIDC 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.

1. In the AM admin UI, go to Realms > *realm name* > Services > Session Property Whitelist Service.

2. Add `AuthLevel` to the Allowlisted Session Property Names field.

3. Save your changes.

#### Configure the provider

Perform this task to set up an OAuth 2.0 provider to use your custom script.

1. [Configure the provider](customizing-oauth2-scopes.html#configure-scripted-oauth2-plugin) and make sure the following properties are set:

   * OIDC Claims Plugin Type to `SCRIPTED`.

   * OIDC Claims Script to the name of your custom script.

2. Save your changes.

3. Switch to the Advanced OpenID Connect tab to always return scope-derived claims in the ID token.

4. Select Always Return Claims in ID Tokens.

   |   |                                                                                                                                                                                                                                                                          |
   | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
   |   | 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](../am-oidc1/understanding-openid-connect-scopes-and-claims.html#request-claims-tokens). |

5. Save your changes.

#### Create a client application

Create a *public* OAuth 2.0 client to use in the authorization request.

1. In the AM admin UI, go to Realms > *realm name* > Applications > OAuth 2.0 > Clients, and click Add Client.

2. Enter the following values:

   * **Client ID**: `myClient`

   * **Client secret**: `mySecret`

   * **Redirection URIs**: `https://www.example.com:443/callback`

   * **Scope(s)**: `openid` `profile`

3. Click Create.

4. On the Core tab, set Client type to `Public`, and click Save.

5. On the Advanced tab, set the following values:

   * **Response Types**: `token id_token`

   * **Grant Types**: `Implicit`

   * **Token Endpoint Authentication Method**: `none`

6. Save your changes.

AM is now prepared for you to try this sample user info claims script.

#### Try the script

To try your custom script, use the [Implicit grant](oauth2-implicit-grant.html) flow as demonstrated in the following steps.

1. Log in to AM as a test user, for example:

   ```bash
   $ curl \
   --request POST \
   --header "Content-Type: application/json" \
   --header "X-OpenAM-Username: bjensen" \
   --header "X-OpenAM-Password: Ch4ng31t" \
   --header "Accept-API-Version: resource=2.0, protocol=1.0" \
   'https://am.example.com:8443/am/json/realms/root/realms/alpha/authenticate'
   {
       "tokenId":"AQIC5wM…​TU3OQ*",
       "successUrl":"/am/console",
       "realm":"/alpha"
   }
   ```

   Copy the SSO token value returned as `tokenId` in the output. You'll need this value in the next step.

2. Invoke the authorization server's [/oauth2/authorize](oauth2-authorize-endpoint.html) 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:

   ```bash
   $ 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://am.example.com:8443/am/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.

1. Call the [/oauth2/idtokeninfo](../am-oidc1/rest-api-oidc-idtoken-validation.html) endpoint to inspect the session property claim values, including the ID token obtained from the previous request.

   For example:

   ```bash
   $ curl \
   --request POST \
   --user myClient:mySecret \
   --data 'id_token=eyJ0eXA…​7QdQpg' \
   "https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/idtokeninfo"
   {
     "at_hash":"PZg5xZsIlFtRSfg8MAWhWg",
     "sub":"(usr!bjensen)",
     "auditTrackingId":"2e5c7611-4a61-4001-8739-f714d43e9da2-881454",
     "subname":"bjensen",
     "iss":"https://am.example.com:8443/am/oauth2",
     "tokenName":"id_token",
     "given_name":"Babs",
     "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":"bjensen",
     "realm":"/alpha",
     "exp":1676364398,
     "tokenType":"JWTToken",
     "iat":1676360798,
     "family_name":"Jensen"
   }
   ```

   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 OIDC claims script that adds a groups claim to the profile scope:

1. [Create the script](#config-oidc-plugin-groups)

2. [Allowlist the Java class](#allowlist-java-class)

3. [Configure the provider](#configure-provider-claims-id-token-groups)

4. [Create a client application](#create-oidc-client-groups)

5. [Try the script](#try-oidc-plugin-groups)

This example adds group membership details to the ID token and uses the [/oauth2/idtokeninfo](../am-oidc1/rest-api-oidc-idtoken-validation.html) endpoint to inspect the groups claim values.

#### Create the script

This task describes how to modify the default script to map a groups claim.

This example uses a legacy script. Find a next-generation example [here](#example-oidc-claims-nextgen).

1. In the AM admin UI, go to Realms > *realm name* > Scripts, and click OIDC Claims Script.

2. In the Script field:

   * Groovy

   * JavaScript

   - Import the `com.sun.identity.idm.IdType` class into the script:

     ```javascript
     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 the `name` claim in the `claimAttributes` section as follows:

     ```javascript
     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 a `ROLE_` prefix. |

   - Add the new claim to the `profile` scope in the claims map:

     ```javascript
     scopeClaimsMap = [
       "email": [ "email" ],
       ...
       "profile": [ "given_name", "zoneinfo", "family_name", "locale", "name", "groups" ]
     ```

   * Add the new `groups` claim to the `profile` scope in the `utils.setScopeClaimsMap` section:

     ```javascript
     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 the `phone_number` claim in the `utils.setClaimResolvers` section as follows:

     ```javascript
     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;
             }
         });
     ```

3. Save your changes.

The default OIDC 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.

1. In the AM admin UI, go to Configure > Global Services > Scripting > Secondary Configurations > OIDC\_CLAIMS > Secondary Configurations > engineConfiguration.

2. Add `com.sun.identity.idm.IdType` to the Java class whitelist field.

3. Save your changes.

#### Configure the provider

Perform this task to set up an OAuth 2.0 provider to use your custom script.

1. [Configure the provider](customizing-oauth2-scopes.html#configure-scripted-oauth2-plugin) and make sure the following properties are set:

   * OIDC Claims Plugin Type to `SCRIPTED`.

   * OIDC Claims Script to the name of your custom script.

2. Save your changes.

3. Switch to the Advanced OpenID Connect tab to always return scope-derived claims in the ID token.

4. Select Always Return Claims in ID Tokens.

   |   |                                                                                                                                                                                                                                                                          |
   | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
   |   | 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](../am-oidc1/understanding-openid-connect-scopes-and-claims.html#request-claims-tokens). |

5. Save your changes.

#### Create a client application

Create a *public* OAuth 2.0 client to use in the authorization request.

1. In the AM admin UI, go to Realms > *realm name* > Applications > OAuth 2.0 > Clients, and click Add Client.

2. Enter the following values:

   * **Client ID**: `myClient`

   * **Client secret**: `mySecret`

   * **Redirection URIs**: `https://www.example.com:443/callback`

   * **Scope(s)**: `openid` `profile`

3. Click Create.

4. On the Core tab, set Client type to `Public`, and click Save.

5. On the Advanced tab, set the following values:

   * **Response Types**: `token id_token`

   * **Grant Types**: `Implicit`

   * **Token Endpoint Authentication Method**: `none`

6. Save your changes.

AM is now prepared for you to try this sample user info claims script.

#### Try the script

To try your custom script, use the [Implicit grant](oauth2-implicit-grant.html) flow as demonstrated in the following steps.

1. Log in to AM as a test user, for example:

   ```bash
   $ curl \
   --request POST \
   --header "Content-Type: application/json" \
   --header "X-OpenAM-Username: bjensen" \
   --header "X-OpenAM-Password: Ch4ng31t" \
   --header "Accept-API-Version: resource=2.0, protocol=1.0" \
   'https://am.example.com:8443/am/json/realms/root/realms/alpha/authenticate'
   {
       "tokenId":"AQIC5wM…​TU3OQ*",
       "successUrl":"/am/console",
       "realm":"/alpha"
   }
   ```

   Copy the SSO token value returned as `tokenId` in the output. You'll need this value in the next step.

2. Invoke the authorization server's [/oauth2/authorize](oauth2-authorize-endpoint.html) 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:

   ```bash
   $ 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://am.example.com:8443/am/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.

1. Call the [/oauth2/idtokeninfo](../am-oidc1/rest-api-oidc-idtoken-validation.html) endpoint to inspect the groups claim values, including the ID token obtained from the previous request.

   For example:

   ```bash
   $ curl \
   --request POST \
   --user myClient:mySecret \
   --data 'id_token=eyJ0eXA…​7QdQpg' \
   "https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/idtokeninfo"
   {
     "at_hash":"PZg5xZsIlFtRSfg8MAWhWg",
     "sub":"(usr!bjensen)",
     "auditTrackingId":"2e5c7611-4a61-4001-8739-f714d43e9da2-881454",
     "subname":"bjensen",
     "iss":"https://am.example.com:8443/am/oauth2",
     "tokenName":"id_token",
     "groups": [
        "supervisors",
        "employees"
     ],
     "given_name":"Babs",
     "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":"bjensen",
     "realm":"/alpha",
     "exp":1676364398,
     "tokenType":"JWTToken",
     "iat":1676360798,
     "family_name":"Jensen"
   }
   ```

   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 OIDC claims script that overrides the `aud` (audience) and `iss` (issuer) claims:

1. [Create the script](#config-oidc-plugin-override)

2. [Configure the provider](#configure-provider-claims-id-token-override)

3. [Create a client application](#create-oidc-client-override)

4. [Try the script](#try-oidc-plugin-override)

This example overrides the `aud` and `iss` claims in the ID token and uses the [/oauth2/idtokeninfo](../am-oidc1/rest-api-oidc-idtoken-validation.html) endpoint to inspect the overridden claims.

|   |                                                                                                                                                                                                                                                                            |
| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | These steps override the `aud` and `iss` claims, but the same steps can be used to override any of the core OIDC claims.For information about the core OIDC claims, refer to the [ID Token data structure](https://openid.net/specs/openid-connect-core-1_0.html#IDToken). |

#### Create the script

This task describes how to modify the default script to override the `aud` and `iss` claims.

This example uses a legacy script. Find a next-generation example [here](#example-oidc-claims-nextgen).

1. In the AM admin UI, go to Realms > *realm name* > Scripts, and click OIDC Claims Script.

2. 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 an `iss` override as a string:

     ```javascript
     computedClaims = claimsToResolve.collectEntries() { claim ->
         result = computeClaim(claim)
     }

     computedClaims.put("iss", "https://example.com")
     ```

   - Then add an `aud` override as an array:

     ```javascript
     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 an `iss` override as a string:

     ```javascript
     computedClaims.put("iss", "https://example.com")

       return computedClaims;
     ```

   * Then add an `aud` override as an array:

     ```javascript
     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 called `testClient` for testing purposes. |

3. Save your changes.

The default OIDC claims script is now amended to override claims.

#### Configure the provider

Perform this task to set up an OAuth 2.0 provider to use your custom script.

1. [Configure the provider](customizing-oauth2-scopes.html#configure-scripted-oauth2-plugin) and make sure the following properties are set:

   * OIDC Claims Plugin Type to `SCRIPTED`.

   * OIDC Claims Script to the name of your custom script.

2. Save your changes.

3. Switch to the Advanced OpenID Connect tab to always return scope-derived claims in the ID token.

4. Select Always Return Claims in ID Tokens.

   |   |                                                                                                                                                                                                                                                                          |
   | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
   |   | 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](../am-oidc1/understanding-openid-connect-scopes-and-claims.html#request-claims-tokens). |

5. Save your changes.

#### Create a client application

Create a *public* OAuth 2.0 client to use in the authorization request.

1. In the AM admin UI, go to Realms > *realm name* > Applications > OAuth 2.0 > Clients, and click Add Client.

2. Enter the following values:

   * **Client ID**: `myClient`

   * **Client secret**: `mySecret`

   * **Redirection URIs**: `https://www.example.com:443/callback`

   * **Scope(s)**: `openid` `profile`

3. Click Create.

4. On the Core tab, set Client type to `Public`, and click Save.

5. On the Advanced tab, set the following values:

   * **Response Types**: `token id_token`

   * **Grant Types**: `Implicit`

   * **Token Endpoint Authentication Method**: `none`

6. On the OAuth2 Provider Overrides tab, select Enable OAuth2 Provider Overrides.

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

8. Save your changes.

AM is now prepared for you to try this sample OIDC claims script.

#### Try the script

To try your custom script, use the [Implicit grant](oauth2-implicit-grant.html) flow as demonstrated in the following steps.

1. Log in to AM as a test user, for example:

   ```bash
   $ curl \
   --request POST \
   --header "Content-Type: application/json" \
   --header "X-OpenAM-Username: bjensen" \
   --header "X-OpenAM-Password: Ch4ng31t" \
   --header "Accept-API-Version: resource=2.0, protocol=1.0" \
   'https://am.example.com:8443/am/json/realms/root/realms/alpha/authenticate'
   {
       "tokenId":"AQIC5wM…​TU3OQ*",
       "successUrl":"/am/console",
       "realm":"/alpha"
   }
   ```

   Copy the SSO token value returned as `tokenId` in the output. You'll need this value in the next step.

2. Invoke the authorization server's [/oauth2/authorize](oauth2-authorize-endpoint.html) 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:

   ```bash
   $ 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://am.example.com:8443/am/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.

1. Call the [/oauth2/idtokeninfo](../am-oidc1/rest-api-oidc-idtoken-validation.html) endpoint to inspect the overridden claims, including the ID token obtained from the previous request.

   For example:

   ```bash
   $ curl \
   --request POST \
   --user myClient:mySecret \
   --data 'id_token=eyJ0eXA…​7QdQpg' \
   "https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/idtokeninfo"
   {
     "at_hash":"PZg5xZsIlFtRSfg8MAWhWg",
     "sub":"(usr!bjensen)",
     "auditTrackingId":"2e5c7611-4a61-4001-8739-f714d43e9da2-881454",
     "subname":"bjensen",
     "iss":"https://example.com",
     "tokenName":"id_token",
     "given_name":"Babs",
     "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":"bjensen",
     "realm":"/alpha",
     "exp":1676364398,
     "tokenType":"JWTToken",
     "iat":1676360798,
     "family_name":"Jensen"
   }
   ```

   Verify the response contains the overridden `iss` and `aud` values.

## Example using a next-generation script

The following example demonstrates how to add a custom claim to the profile scope using a next-generation script.

1. [Create the OIDC claims script](#config-oidc-plugin-ng)

2. [Create a client application](#create-oidc-client-ng)

3. [Try the script](#try-oidc-plugin-ng)

The example uses the [/oauth2/userinfo](../am-oidc1/rest-api-oidc-userinfo-endpoint.html) endpoint to inspect the custom claim values.

### Create the OIDC claims script

This task describes how to create a new next-generation script to map custom claims.

1. In the AM admin UI, go to Realms > *realm name* > Scripts > + New Script, enter the following values:

   * Name: `Demo OIDC claims`

   * Script Type: `OIDC Claims`

   * Evaluator Version: `Next Generation`

2. In the Script field, paste the following JavaScript:

   ```javascript
   (function () {
       var computedClaims = {};
       var compositeScopes = {};

       function getAttribute(attrName) {
           var values = identity.getAttributeValues(attrName);
           return (values && values.size() > 0 ? values[0] : null);
       }

       // Use the 'identity' binding to fetch user profile data
       if (identity) {

           var cn = getAttribute('cn');
           var sn = getAttribute('sn');
           var gn = getAttribute('givenName');

           // Map standard OIDC claims
           if (cn) computedClaims['name'] = cn;
           if (sn) computedClaims['family_name'] = sn;
           if (gn) computedClaims['given_name'] = gn;

           // Add custom claim
           if (gn && sn) {
               computedClaims['custom_string'] = gn + "_" + sn;
           }
       }

       // Map claims to requested scopes
       for each(var scope in scopes) {
           // Map claims to the 'profile' scope, including our custom ones
           if (scope === 'profile') {
               compositeScopes['profile'] = [
                   'name',
                   'family_name',
                   'given_name',
                   'custom_string'
               ];
           } else if (scope === 'email') {
               compositeScopes['email'] = ['email'];
           }
       }
       // The script must return an object with exactly two properties:
       // 'values' and 'compositeScopes'
       return {
           values: computedClaims,
           compositeScopes: compositeScopes
       };
   }());
   ```

3. Save your changes.

The new OIDC claims script is now ready to retrieve a custom claim for the `profile` scope.

### Configure the provider

Perform this task to set up an OAuth 2.0 provider to use your custom script.

1. [Configure the provider](customizing-oauth2-scopes.html#configure-scripted-oauth2-plugin) and make sure the following properties are set:

   * OIDC Claims Plugin Type to `SCRIPTED`.

   * OIDC Claims Script to the name of your custom script.

2. Save your changes.

3. Switch to the Advanced OpenID Connect tab to always return scope-derived claims in the ID token.

4. Select Always Return Claims in ID Tokens.

   |   |                                                                                                                                                                                                                                                                          |
   | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
   |   | 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](../am-oidc1/understanding-openid-connect-scopes-and-claims.html#request-claims-tokens). |

5. Save your changes.

### Create a client application

Create a *public* OAuth 2.0 client to use in the authorization request.

1. In the AM admin UI, go to Realms > *realm name* > Applications > OAuth 2.0 > Clients, and click Add Client.

2. Enter the following values:

   * **Client ID**: `myClient`

   * **Client secret**: `mySecret`

   * **Redirection URIs**: `https://www.example.com:443/callback`

   * **Scope(s)**: `openid` `profile`

3. Click Create.

4. On the Core tab, set Client type to `Public`, and click Save.

5. On the Advanced tab, set the following values:

   * **Response Types**: `token id_token`

   * **Grant Types**: `Implicit`

   * **Token Endpoint Authentication Method**: `none`

6. Save your changes.

AM is now prepared for you to try this sample user info claims script.

### Try the script

To try your custom script, use the [Implicit grant](oauth2-implicit-grant.html) flow as demonstrated in the following steps.

1. Log in to AM as a test user, for example:

   ```bash
   $ curl \
   --request POST \
   --header "Content-Type: application/json" \
   --header "X-OpenAM-Username: bjensen" \
   --header "X-OpenAM-Password: Ch4ng31t" \
   --header "Accept-API-Version: resource=2.0, protocol=1.0" \
   'https://am.example.com:8443/am/json/realms/root/realms/alpha/authenticate'
   {
       "tokenId":"AQIC5wM…​TU3OQ*",
       "successUrl":"/am/console",
       "realm":"/alpha"
   }
   ```

   Copy the SSO token value returned as `tokenId` in the output. You'll need this value in the next step.

2. Invoke the authorization server's [/oauth2/authorize](oauth2-authorize-endpoint.html) 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:

   ```bash
   $ 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://am.example.com:8443/am/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
   ```

3. Copy the value of the `access_token` appended to the redirection URI in the response. You'll need this value in the next step.

4. Call the [/oauth2/userinfo](../am-oidc1/rest-api-oidc-userinfo-endpoint.html) endpoint to inspect the custom claim values, including the access token obtained from the previous request.

   For example:

   ```bash
   $ curl \
   --request GET \
   --header "Authorization: Bearer <access-token>" \
   'https://am.example.com:8443/am/oauth2/realms/root/realms/alpha/userinfo'
   {
     "name":"bjensen",
     "given_name":"Babs",
     "family_name":"Jensen",
     "custom_string": "Babs_Jensen"
   }
   ```

Verify the response contains the custom claim, `custom_string`, added by the script.
