---
title: Access token modification
description: Use the access token modification extension point to add or change key-value pairs in OAuth 2.0 access tokens before issuing them to clients
component: pingam
version: 7.5
page_id: pingam:am-oauth2:modifying-access-tokens-scripts
canonical_url: https://docs.pingidentity.com/pingam/8.1/am-oauth2/modifying-access-tokens-scripts.html
llms_txt: https://docs.pingidentity.com/pingam/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
keywords: ["OAuth 2.0", "Customization", "Scripting", "Java", "Plugins"]
page_aliases: ["oauth2-guide:modifying-access-tokens-scripts.adoc"]
superseded_by: https://docs.pingidentity.com/pingam/8.1/am-oauth2/modifying-access-tokens-scripts.html
section_ids:
  about_modifying_access_tokens: About modifying access tokens
  modifying-access-tokens-scripts-prepare: Example access token modification plugin
  prepare-atm-plugin: Prepare AM to modify access tokens
  configure-atm-plugin: Configure AM to use the custom access token modification script
  create-atm-client: Create an OAuth2 client for authorization
  try-atm-script: Try the custom access token modification script
  proc-token-mod-get-auth-code: Obtain an authorization code
  proc-token-mod-get-access-token: Exchange an authorization code for an access token
  proc-token-mod-introspect-access-token: Introspect an access token to verify access token modification
  scripting-api-access-token-modification: Access token modification scripting API
---

# Access token modification

Use this extension point to modify the key-value pairs in an OAuth 2.0 access token. For example, you could make a REST call to an external service and add or change a key-value pair in the access token based on the response before issuing the token to the OAuth 2.0 client.

* Default script

  Learn more about viewing the default script, including the available script properties, in [oauth2-access-token-modification.groovy](../am-scripting/sample-scripts.html#oauth2-access-token-modification-groovy).

  To view or modify the default script in the AM admin UI, go to Realms > *realm name* > Scripts and select OAuth2 Access Token Modification Script.

* Java interface

  `org.forgerock.oauth2.core.plugins.AccessTokenModifier`

* Java sample

> **Collapse: Show Sample Code**
>
> ```java
> /*
>  * 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 org.forgerock.oauth2.core.AccessToken;
> import org.forgerock.oauth2.core.OAuth2Request;
> import org.forgerock.oauth2.core.plugins.AccessTokenModifier;
>
> /**
>  * Custom implementation of the Access Token Modifier
>  * plugin interface {@link org.forgerock.oauth2.core.plugins.AccessTokenModifier}
>  *
>  * <li>
>  * In this example the {@code modifyAccessToken} method adds an additional field to the token.
>  * </li>
>  *
>  */
> public class CustomAccessTokenModifier implements AccessTokenModifier {
>
>     @Override
>     public void modifyAccessToken(AccessToken accessToken, OAuth2Request request) {
>         //Field to always include in token
>         accessToken.setField("additional", "field");
>     }
> }
> ```

## About modifying access tokens

You can modify both [client-side](stateless-stateful-tokens.html#client-side-tokens) and [server-side](stateless-stateful-tokens.html#server-side-tokens) access tokens. Modifications are stored permanently in the issued JWT for client-side tokens or in the CTS for server-side access tokens. You can also modify [macaroons](oauth2-macaroons.html) used in place of regular tokens. In this case, you implement the plugin to modify the key pairs in the token and, optionally, to add caveats. Learn more in [MacaroonToken](../_attachments/apidocs/org/forgerock/openam/oauth2/token/macaroon/MacaroonToken.html) interface.

When issuing modified access tokens, consider the following important points:

* Removing or changing native properties could render the access token unusable.

  AM requires that certain native properties are present in the access token to consider it valid. Removing or modifying these properties could cause the OAuth 2.0 flows to break.

  |   |                                                                                                                                                                                      |
  | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  |   | The [AccessToken API documentation](../_attachments/apidocs/org/forgerock/oauth2/core/AccessToken.html) indicates the native properties and warns against changing or removing them. |

* Modifying access tokens affects the size of the client-side token or server-side entry.

  Changes made to OAuth 2.0 access tokens directly affects the size of the server-side tokens or the size of the JSON web tokens (JWT) if client-side tokens are enabled.

  You must make sure the token size remains within your client or user-agent size limits.

  Learn more in [Token storage location](stateless-stateful-tokens.html).

## Example access token modification plugin

Complete the following steps to implement a custom access token modification script that sets additional properties in the access token:

1. [Prepare AM to modify access tokens](#prepare-atm-plugin)

2. [Configure AM to use the custom access token modification script](#configure-atm-plugin)

3. [Create an OAuth2 client for authorization](#create-atm-client)

4. [Try the custom access token modification script](#try-atm-script)

|   |                                                                                                                                                                                                 |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | Learn more about configuring AM to use a *Java* access token modification plugin in [Configure AM to use a Java OAuth 2.0 plugin](customizing-oauth2-scopes.html#configure-java-oauth2-plugin). |

### Prepare AM to modify access tokens

The script requires that the authenticated user of the access token has an email address and telephone number in their profile. The script adds the values of these fields to the access token.

1. Log in as an AM administrator, for example, `amAdmin`.

2. Add an email address and telephone number value to the `demo` user's profile.

   The access token modification script injects the values provided into the OAuth 2.0 access token before it is issued to the resource owner.

   1. Select Realms > *realm name* > Identities.

   2. On the Identities tab, select the `demo` user.

   3. In Email Address, enter a valid address. For example, `demo.user@example.com`.

   4. In Telephone Number, enter a value. For example, `44 117 496 0228`.

   5. Save your changes.

3. Modify the default access token modification script to set additional fields.

   1. Go to Realms > *realm name* > Scripts, and click OAuth2 Access Token Modification Script.

   2. In the Script field:

      * Uncomment the following line, by surrounding with a pair of `*/` and `/*` strings:

        ```groovy
        /* ... */
        accessToken.setField("hello", "world")
        /* ... */
        ```

      * Uncomment the identity attribute lines and add a `null` check before accessing them, for example:

        ```groovy
        /* ... */
        if (identity != null) {
            def attributes = identity.getAttributes(["mail", "telephoneNumber"].toSet())
            accessToken.setField("mail", attributes["mail"])
            accessToken.setField("phone", attributes["telephoneNumber"])
        }
        /* ... */
        ```

        |   |                                                                                                                                                                                                                                     |
        | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
        |   | The `identity` binding is `null` if the resource owner doesn't exist in AM, such as when a JWT bearer grant references an unknown subject.Learn more in the [identity](#scripting-api-access-token-modification) binding reference. |

        |   |                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
        | - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
        |   | To include additional data in the [/oauth2/access_token](oauth2-access_token-endpoint.html) response, edit your script to call the `addExtraData` method. For example:```groovy
        accessToken.addExtraData("hello", "world")
        ```This returns the data as part of the response body in the following way:```json
        {
          "access_token":"sbQZuveFumUDV5R1vVBl6QAGNB8",
          "hello":"world",
          "scope":"write",
          "token_type":"Bearer",
          "expires_in":3599
        }
        ``` |

   3. Save your changes.

### Configure AM to use the custom access token modification script

Perform this task to set up an OAuth 2.0 provider that uses the modified default access token modification script.

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

   * Access Token Modification Plugin Type to `SCRIPTED`.

   * Access Token Modification Plugin Script to `OAuth2 Access Token Modification Script`.

   By default, a new OAuth 2.0 provider uses the default access token modification script.

2. Save your changes.

### Create an OAuth2 client for authorization

Create an OAuth 2.0 client to use in the authorization request.

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

2. Enter the following values:

   * **Client ID**: `myClient`

   * **Client secret**: `forgerock`

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

   * **Scope(s)**: `access|Access to your data`

3. Click Create.

AM is now configured to issue access tokens using the default access token modification script. As the `demo` user, you can now obtain an access token to test the script functionality.

### Try the custom access token modification script

This section demonstrates obtaining an OAuth 2.0 access token that was modified by a script.

First, use the [Authorization code grant](oauth2-authz-grant.html) flow to authenticate with AM as the resource owner, allow the client to access profile data, and receive the authorization code.

Next, exchange the authorization code for an access token.

The access token was altered by the default access token modification script to include:

* The resource owner's telephone number and email address, taken from their profile in AM, which is acting as the authorization server.

* A `hello:world` key-value pair.

Finally, use the introspect endpoint to verify that the access token includes the modified values.

#### Obtain an authorization code

1. In a web browser, go to the [/oauth2/authorize](oauth2-authorize-endpoint.html) endpoint, including the parameters and values configured for the OAuth 2.0 client in the previous section.

   Make sure you specify the correct realm in the endpoint. For example, if the OAuth 2.0 provider is configured for the `/alpha` realm, then use `/oauth2/realms/root/realms/alpha/authorize`.

   For example:

   ```none
   https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/authorize \
   ?client_id=myClient \
   &response_type=code \
   &scope=access \
   &state=abc123 \
   &redirect_uri=https://www.example.com:443/callback
   ```

   The URL is split for readability purposes.

   The AM login page is displayed.

2. Sign on as the `demo` user, with password `Ch4ng31t`.

   The AM OAuth 2.0 consent page is displayed.

3. Review the requested scopes, and click Allow.

   AM redirects the browser to the location specified in the `redirect_uri` parameter, `https://www.example.com:443/callback` in this example, and appends a number of query parameters.

   For example:

   ![OAuth 2.0 authorization code in browser URL bar.](_images/oauth2-authz-code.png)

4. Record the value of the `code` query parameter.

   This is the authorization code and is exchanged for an access token in the next procedure.

#### Exchange an authorization code for an access token

1. Send a POST request to the [/oauth2/access_token](oauth2-access_token-endpoint.html) endpoint, including the authorization code obtained in the previous procedure, and the parameters and values configured for the OAuth 2.0 client earlier.

   For example:

   ```bash
   $ curl \
     --request POST \
     --data "grant_type=authorization_code" \
     --data "code=tH_s2obVRt2_yB6x4OxH1J3eMkU" \
     --data "client_id=myClient" \
     --data "client_secret=forgerock" \
     --data "redirect_uri=https://www.example.com:443/callback" \
     "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/access_token"
   {
     "access_token": "sbQZuveFumUDV5R1vVBl6QAGNB8",
     "scope": "access",
     "token_type": "Bearer",
     "expires_in": 3599
   }
   ```

2. Record the value of the `access_token` property.

   This is the access token; the access token modification script modified the properties. Follow the steps in the next procedure to introspect the token to verify the properties were modified.

#### Introspect an access token to verify access token modification

1. Send a POST request to the [/oauth2/introspect](oauth2-introspect-endpoint.html) endpoint, including the access token obtained in the previous procedure, and the credentials of the OAuth 2.0 client.

   For example:

   ```bash
   $ curl \
     --request POST \
     --data "client_id=myClient" \
     --data "client_secret=forgerock" \
     --data "token=sbQZuveFumUDV5R1vVBl6QAGNB8" \
     "https://openam.example.com:8443/openam/oauth2/realms/root/realms/alpha/introspect"
   {
     "active": true,
     "scope": "access",
     "client_id": "myClient",
     "user_id": "demo",
     "username":"demo",
     "token_type": "Bearer",
     "exp": 1556289970,
     "sub": "(usr!demo)",
     "subname": "demo",
     "iss": "https://openam.example.com:8443/openam/oauth2",
     "auth_level": 0,
     "auditTrackingId": "c6e22be7-6166-402b-9d72-a03134f08c22-8605",
     "hello": "world",
     "mail": [
       "demo.user@example.com"
     ],
     "phone": [
       "+44 117 496 0228"
     ]
   }
   ```

   Notice that the output includes a `hello:world` key-value pair, as well as `mail` and `phone` properties, containing values taken from the user's profile data.

## Access token modification scripting API

The following properties are available to access token modification scripts:

| Binding                                           | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `accessToken`                                     | The OAuth 2.0 access token. Learn more in [AccessToken](../_attachments/apidocs/org/forgerock/oauth2/core/AccessToken.html).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `clientProperties`                                | A map of properties configured in the client profile. Only present if the client was correctly identified.The map has the following keys:- `allowedGrantTypes`

  List of the grant types allowed for the client. Learn more in [GrantType](../_attachments/apidocs/org/forgerock/oauth2/core/GrantType.html).

- `allowedResponseTypes`

  The permitted response types as an array of strings

- `allowedScopes`

  The permitted scope types as an array of strings

- `clientId`

  The client's URI for the request locale.

- `customProperties`

  A map of any custom properties added to the client.

  Lists or maps are included as sub-maps. For example, a custom property of `customMap[Key1]=Value1` is returned as `customMap > Key1 > Value1`.

  To add custom properties to a client, use the AM admin UI. Go to OAuth 2.0 > Clients > *client ID* > Advanced, and update the Custom Properties field.

  Add custom properties as shown in these examples:

  ```bash
  customproperty=custom-value1
  customList[0]=customList-value-0
  customMap[key1]=customMap-value-1
  ```

  Scripts can then access the custom properties in the following way:

  ```javascript
  var customProperties = clientProperties.get("customProperties");
  var property = customProperties.get("myProperty");
  ```

  The map is `null` if AM did not successfully identify the client. |
| `httpClient`                                      | An HTTP client for making external HTTP requests.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `identity`                                        | Represents the resource owner. `null` if the resource owner doesn't exist in AM.An [AMIdentity](../_attachments/apidocs/com/sun/identity/idm/AMIdentity.html) object, or `null`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| [`logger`](customizing-oauth2-scopes.html#logger) | The logger instance for the script.Logger names use the format `scripts.OAUTH2_ACCESS_TOKEN_MODIFICATION.<script UUID>.(<script name>)`.Learn more in [Debug logging](../maintenance/debug-logging.html).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `requestProperties`                               | A map of the properties present in the request.The map has the following keys:- `requestUri`

  The URI as a string

- `realm`

  The realm as a string

- `requestParams`

  A map of request parameters and posted data, where each value is an array of parameters.

  To mitigate the risk of reflection-type attacks, use OWASP best practices when handling these parameters. Learn more in Unsafe use of Reflection.

- `requestHeaders`

  The value of the named request header. Returns a map of `<String, List<String>>` as a native JavaScript object, for example:

  `var ipAddress = requestProperties.requestHeaders["X-Forwarded-For"][0]`

  Header names are case-sensitive.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `scriptName`                                      | The display name of the script.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `scopes`                                          | An array of the requested scopes. For example:`["read", "transfer", "download"]`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `session`                                         | The user's session object if the request contains a session cookie.Learn more in [SSOToken](../_attachments/apidocs/com/iplanet/sso/SSOToken.html).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
