---
title: Scripting required scopes with PingAM
description: This example builds on the example in Validating PingAM access tokens with introspection to use a script to define the scopes that a request requires in an access token.
component: pinggateway
version: 2026
page_id: pinggateway:gateway-guide:oauth2-rs-script-scopes
canonical_url: https://docs.pingidentity.com/pinggateway/2026/gateway-guide/oauth2-rs-script-scopes.html
revdate: 2025-04-01T17:53:34Z
---

# Scripting required scopes with PingAM

This example builds on the example in [Validating PingAM access tokens with introspection](oauth2-rs-introspect.html) to use a script to define the scopes that a request requires in an access token.

* If the request path is `/rs-tokeninfo`, the request requires only the scope `mail`.

* If the request path is `/rs-tokeninfo/employee`, the request requires the scopes `mail` and `employeenumber`.

Before you start, set up and test the example in [Validating PingAM access tokens with introspection](oauth2-rs-introspect.html).

1. Add the following route to PingGateway:

   * Linux

     `$HOME/.openig/config/routes/rs-dynamicscope.json`

   * Windows

     `%appdata%\OpenIG\rs-dynamicscope.json`

   ```json
   {
     "name": "rs-dynamicscope",
     "condition": "${find(request.uri.path, '^/rs-dynamicscope')}",
     "heap": [
       {
         "name": "SystemAndEnvSecretStore-1",
         "type": "SystemAndEnvSecretStore"
       },
       {
         "name": "AmService-1",
         "type": "AmService",
         "config": {
           "agent": {
             "username": "ig_agent",
             "passwordSecretId": "agent.secret.id"
           },
           "secretsProvider": "SystemAndEnvSecretStore-1",
           "url": "http://am.example.com:8088/openam/"
         }
       }
     ],
     "handler": {
       "type": "Chain",
       "config": {
         "filters": [
           {
             "name": "OAuth2ResourceServerFilter-1",
             "type": "OAuth2ResourceServerFilter",
             "config": {
               "scopes": {
                 "name": "myscript",
                 "type": "ScriptableResourceAccess",
                 "config": {
                   "type": "application/x-groovy",
                   "source": [
                     "// Minimal set of required scopes",
                     "def scopes = [ 'mail' ] as Set",
                     "if (request.uri.path =~ /employee$/) {",
                     "  // Require another scope to access this resource",
                     "  scopes += 'employeenumber'",
                     "}",
                     "return scopes"
                   ]
                 }
               },
               "requireHttps": false,
               "accessTokenResolver": {
                 "name": "token-resolver-1",
                 "type": "TokenIntrospectionAccessTokenResolver",
                 "config": {
                   "amService": "AmService-1",
                   "providerHandler": {
                     "type": "Chain",
                     "config": {
                       "filters": [
                         {
                           "type": "HttpBasicAuthenticationClientFilter",
                           "config": {
                             "username": "ig_agent",
                             "passwordSecretId": "agent.secret.id",
                             "secretsProvider": "SystemAndEnvSecretStore-1"
                           }
                         }
                       ],
                       "handler": "ForgeRockClientHandler"
                     }
                   }
                 }
               }
             }
           }
         ],
         "handler": {
           "type": "StaticResponseHandler",
           "config": {
             "status": 200,
             "headers": {
               "Content-Type": [ "text/html; charset=UTF-8" ]
             },
             "entity": "<html><body><h2>Decoded access_token: ${contexts.oauth2.accessToken.info}</h2></body></html>"
           }
         }
       }
     }
   }
   ```

   Source: [rs-dynamicscope.json](../_attachments/config/routes/rs-dynamicscope.json)

2. Test the setup with the `mail` scope only:

   1. In a terminal, use a `curl` command to retrieve an access token with the scope `mail`:

      ```console
      $ mytoken=$(curl -s \
      --user "client-application:password" \
      --data "grant_type=password&username=demo&password=Ch4ng31t&scope=mail" \
      http://am.example.com:8088/openam/oauth2/access_token | jq -r ".access_token")
      ```

   2. Confirm that the access token is returned for the `/rs-dynamicscope` path:

      ```console
      $ curl -v \
      --cacert /path/to/secrets/ig.example.com-certificate.pem \
      --header "Authorization: Bearer ${mytoken}" \
      https://ig.example.com:8443/rs-dynamicscope
      ```

      Output

      ```none
      {
        active = true,
        scope = mail,
        client_id = client-application,
        user_id = demo,
        token_type = Bearer,
        exp = 158...907,
        sub = demo,
        iss = http://am.example.com:8088/openam/oauth2, ...
        ...
      }
      ```

   3. Confirm that the access token **is not** returned for the `/rs-dynamicscope/employee` path:

      ```console
      $ curl -v \
      --cacert /path/to/secrets/ig.example.com-certificate.pem \
      --header "Authorization: Bearer ${mytoken}" \
      https://ig.example.com:8443/rs-dynamicscope/employee
      ```

3. Test the setup with the scopes `mail` and `employeenumber`:

   1. In a terminal window, use a `curl` command similar to the following to retrieve an access token with the scopes `mail` and `employeenumber`:

      ```console
      $ mytoken=$(curl -s \
      --user "client-application:password" \
      --data "grant_type=password&username=demo&password=Ch4ng31t&scope=mail%20employeenumber" \
      http://am.example.com:8088/openam/oauth2/access_token | jq -r ".access_token")
      ```

   2. Confirm that the access token **is** returned for the `/rs-dynamicscope/employee` path:

      ```console
      $ curl -v
      --cacert /path/to/secrets/ig.example.com-certificate.pem \
      --header "Authorization: Bearer ${mytoken}"
      https://ig.example.com:8443/rs-dynamicscope/employee
      ```
