---
title: Encrypted PingAM tokens with KeyStoreSecretStore
description: This page shows how to validate encrypted access tokens with the StatelessAccessTokenResolver using a JwkSetSecretStore.
component: pinggateway
version: 2026
page_id: pinggateway:gateway-guide:oauth2-rs-stateless-encrypted
canonical_url: https://docs.pingidentity.com/pinggateway/2026/gateway-guide/oauth2-rs-stateless-encrypted.html
revdate: 2025-04-01T17:53:34Z
section_ids:
  set_up_encryption_keys: Set up encryption keys
  proc-stateless-setup-keystore: Validate tokens
---

# Encrypted PingAM tokens with KeyStoreSecretStore

This page shows how to validate encrypted access tokens with the StatelessAccessTokenResolver using a [JwkSetSecretStore](../reference/JwkSetSecretStore.html).

## Set up encryption keys

1. Locate the following directories for keys, keystores, and certificates, and in a terminal create variables for them:

   * Directory where the keystore is created: `keystore_directory`

   * AM keystore directory: `am_keystore_directory`

   * PingGateway keystore directory: `ig_keystore_directory`

2. Set up keys for AM:

   1. Generate the encryption key:

      ```console
      $ keytool -genseckey \
      -alias encryption-key \
      -dname "CN=ig.example.com, OU=example, O=com, L=fr, ST=fr, C=fr" \
      -keystore "$am_keystore_directory/AM_keystore.p12" \
      -storetype PKCS12 \
      -storepass "password" \
      -keyalg AES \
      -keysize 256
      ```

   2. List the keys in the AM keystore:

      ```console
      $ keytool -list \
      -v \
      -keystore "$am_keystore_directory/AM_keystore.p12" \
      -storepass "password" \
      -storetype PKCS12
      ```

      Output

      ```
      ...
      Your keystore contains 1 entry
      Alias name: encryption-key
      ```

   3. Add a file called `keystore.pass`, with the content `password`:

      ```console
      $ cd $am_keystore_directory
      $ echo -n 'password' > keystore.pass
      ```

      |   |                                                                                                      |
      | - | ---------------------------------------------------------------------------------------------------- |
      |   | Make sure the password file contains only the password, with no trailing spaces or carriage returns. |

      The filename corresponds to the secret ID of the store password and entry password for the KeyStoreSecretStore.

   4. Restart AM.

3. Set up keys for PingGateway:

   1. Import `encryption-key` into the PingGateway keystore, with the alias `decryption-key`:

      ```console
      $ keytool -importkeystore \
      -srcalias encryption-key \
      -srckeystore "$am_keystore_directory/AM_keystore.p12" \
      -srcstoretype PKCS12 \
      -srcstorepass "password" \
      -destkeystore "$ig_keystore_directory/IG_keystore.p12" \
      -deststoretype PKCS12 \
      -destalias decryption-key \
      -deststorepass "password" \
      -destkeypass "password"
      ```

   2. List the keys in the PingGateway keystore:

      ```console
      $ keytool -list \
      -v \
      -keystore "$ig_keystore_directory/IG_keystore.p12" \
      -storepass "password" \
      -storetype PKCS12
      ```

      Output

      ```
      ...
      Your keystore contains 1 entry
      Alias name: decryption-key
      ```

   3. In the PingGateway configuration, set an environment variable for the keystore password:

      ```console
      $ export KEYSTORE_SECRET_ID='cGFzc3dvcmQ='
      ```

   4. Restart PingGateway.

## Validate tokens

1. Set up AM:

   1. Set up AM as described in [Validate tokens](oauth2-rs-stateless-signed-ksss.html#proc-oauth2-rs-stateless-signed-ksss).

   2. Add a mapping for the encryption keystore:

      1. Select [icon: eye-slash, set=fa]Secret Stores > `keystoresecretstore`.

      2. Select the Mappings tab, and add a mapping with the following values:

         * Secret Label : `am.services.oauth2.stateless.token.encryption`

         * Alias : `encryption-key`

   3. Enable token encryption on the OAuth 2.0 Authorization Provider:

      1. Select Services > OAuth2 Provider.

      2. On the Advanced tab, select Encrypt Client-Side Tokens.

2. Set up PingGateway:

   1. Set up PingGateway for HTTPS, as described in [Configure PingGateway for TLS (server-side)](../installation-guide/securing-connections.html#server-side-tls).

   2. Add the following route to PingGateway, replacing `<ig_keystore_directory>`:

      * Linux

        `$HOME/.openig/config/routes/rs-stateless-encrypted.json`

      * Windows

        `%appdata%\OpenIG\config\routes\rs-stateless-encrypted.json`

      ```json
      {
        "name": "rs-stateless-encrypted",
        "condition": "${find(request.uri.path, '/rs-stateless-encrypted')}",
        "heap": [
          {
            "name": "SystemAndEnvSecretStore-1",
            "type": "SystemAndEnvSecretStore"
          },
          {
            "name": "KeyStoreSecretStore-1",
            "type": "KeyStoreSecretStore",
            "config": {
              "file": "<ig_keystore_directory>/IG_keystore.p12",
              "storeType": "PKCS12",
              "storePasswordSecretId": "keystore.secret.id",
              "entryPasswordSecretId": "keystore.secret.id",
              "secretsProvider": "SystemAndEnvSecretStore-1",
              "mappings": [
                {
                  "secretId": "stateless.access.token.decryption.key",
                  "aliases": [ "decryption-key" ]
                }
              ]
            }
          }
        ],
        "handler": {
          "type": "Chain",
          "capture": "all",
          "config": {
            "filters": [ {
              "name": "OAuth2ResourceServerFilter-1",
              "type": "OAuth2ResourceServerFilter",
              "config": {
                "scopes": [ "myscope" ],
                "requireHttps": false,
                "accessTokenResolver": {
                  "type": "StatelessAccessTokenResolver",
                  "config": {
                    "secretsProvider": "KeyStoreSecretStore-1",
                    "issuer": "http://am.example.com:8088/openam/oauth2",
                    "decryptionSecretId": "stateless.access.token.decryption.key"
                  }
                }
              }
            } ],
            "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-stateless-encrypted.json](../_attachments/config/routes/rs-stateless-encrypted.json)

      Notice the following features of the route compared to `rs-stateless-signed.json` from [Validate tokens](oauth2-rs-stateless-signed-ksss.html#proc-oauth2-rs-stateless-signed-ksss).

      * The route matches requests to `/rs-stateless-encrypted`.

      * The OAuth2ResourceServerFilter and KeyStoreSecretStore refer to the configuration for a decryption key instead of a verification key.

3. Test the setup

   1. Get an access token for the demo user, using the scope `myscope`:

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

   2. Display the token:

      ```console
      $ echo ${mytoken}
      ```

      Note that the token is structured as an encrypted token.

   3. Access the route by providing the token returned in the previous step:

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

      Output

      ```
      ...
      Decoded access_token: {
      sub=demo,
      cts=OAUTH2_STATELESS_GRANT,
      ...
      ```
