---
title: JwkSetHandler
description: Expose cryptographic keys as a JWK set. Use this handler to reuse exposed keys for their assigned purpose in a downstream application.
component: pinggateway
version: 2025.9
page_id: pinggateway:reference:JwkSetHandler
canonical_url: https://docs.pingidentity.com/pinggateway/2026/reference/JwkSetHandler.html
llms_txt: https://docs.pingidentity.com/pinggateway/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
superseded_by: https://docs.pingidentity.com/pinggateway/2026/reference/JwkSetHandler.html
section_ids:
  JwkSetHandler-usage: Usage
  JwkSetHandler-example: Examples
  JwkSetHandler-moreinfo: More information
---

# JwkSetHandler

Expose cryptographic keys as a JWK set. Use this handler to reuse exposed keys for their assigned purpose in a downstream application.

Consider the following limitations:

* When the public key isn't available, the corresponding private key can't be exposed.

  |   |                                                         |
  | - | ------------------------------------------------------- |
  |   | You aren't recommended to expose private keys as a JWK. |

* Keys in secure storage, such as a Hardware Security Module (HSM) or remote server, can't be exposed.

You can find a description of how secrets are managed in [About secrets](../security-guide/keys.html#about-secrets).

You can find more information about JWKs and JWK Sets in [JSON Web Key (JWK)](https://www.rfc-editor.org/rfc/rfc7517).

## Usage

```none
{
  "name": string,
  "type": "JwkSetHandler",
  "config": {
    "secretsProvider": SecretsProvider reference,
    "purposes": [ object, ... ],
    "exposePrivateSecrets": configuration expression<boolean>
  }
}
```

* `"secretsProvider"`: *SecretsProvider [reference](preface.html#definition-reference), required*

  The [SecretsProvider](SecretsProvider.html) containing secrets to expose in the JwkSet.

* `"purposes"`: *array of [objects](preface.html#definition-object), required*

  One or more purposes for the JwkSet key.

```none
{
  "purposes": [
    {
      "secretId": configuration expression<secret-id>,
      "keyUsage": configuration expression<enumeration>
      "jwkAlgorithm": configuration expression<string>
    },
    ...
  ]
}
```

* `"secretId"`: *configuration expression<[secret-id](preface.html#definition-secretid)>, required*

  The secret ID of the key to be exposed in the JwkSet.

  This secret ID must point to a [CryptoKey](../security-guide/keys.html#secret-types).

* `"keyUsage"`: *configuration expression<[enumeration](preface.html#definition-enumeration)>, required*

  The allowed use of the key:

  * `AGREE_KEY`: Export the private key used in the key agreement protocol, for example, Diffie-Hellman.

  * `ENCRYPT`: Export the public key used to encrypt data.

  * `DECRYPT`: Export the private key used to decrypt data.

  * `SIGN`: Export the private key used to sign data.

  * `VERIFY`: Export the public key used to verify signature data.

  * `WRAP_KEY`: Export the public key used to encrypt (wrap) other keys.

  * `UNWRAP_KEY`: Export the private key used to decrypt (unwrap) other keys.

* `"jwkAlgorithm"`: *configuration expression<[string](preface.html#definition-string)>, optional*

  The algorithm to include in the generated JWK `alg` parameter.

  PingGateway validates the algorithm against the known possible values. PingGateway doesn't communicate the actual algorithm used to generate the key.

  Learn more about the `alg` parameter in [RFC 7517, Section 4.4](https://www.rfc-editor.org/rfc/rfc7517.html#section-4.4).

* `exposePrivateSecrets`: *configuration expression<[boolean](preface.html#definition-boolean)>, optional*

  A flag indicating whether to publish private keys in a JWK set. As a security safeguard, this property is `false` by default to prevent the accidental exposure of private keys.

  `true`: Publish both public and private keys in the JWK set `false`: Publish only public keys in the JWK set

  Default: `false`

## Examples

This example uses a JwkSetHandler to expose a signing key used by the JwtBuilderFilter:

1. Set an environment variable for the base64-encoded secret to sign the JWT:

   ```console
   $ export SIGNING_KEY_SECRET_ID='cGFzc3dvcmQ='
   ```

2. Add the following route to PingGateway:

   * Linux

     `$HOME/.openig/config/routes/jwksethandler.json`

   * Windows

     `%appdata%\OpenIG\config\routes\jwksethandler.json`

   ```json
   {
     "name": "jwksethandler",
     "condition": "${find(request.uri.path, '/jwksethandler')}",
     "heap": [
       {
         "name": "SecretKeyPropertyFormat-1",
         "type": "SecretKeyPropertyFormat",
         "config": {
           "format": "BASE64",
           "algorithm": "AES"
         }
       },
       {
         "name": "SystemAndEnvSecretStore-1",
         "type": "SystemAndEnvSecretStore",
         "config": {
           "mappings": [{
             "secretId": "signing.key.secret.id",
             "format": "SecretKeyPropertyFormat-1"
           }]
         }
       }
     ],
     "handler": {
       "type": "Chain",
       "config": {
         "filters": [
           {
             "name": "JwtBuilderFilter-1",
             "type": "JwtBuilderFilter",
             "config": {
               "template": {
                 "name": "${contexts.userProfile.commonName}",
                 "email": "${contexts.userProfile.rawInfo.mail[0]}"
               },
               "secretsProvider": "SystemAndEnvSecretStore-1",
               "signature": {
                 "secretId": "signing.key.secret.id",
                 "algorithm": "HS256"
               }
             }
           }
         ],
         "handler": {
           "type": "JwkSetHandler",
           "config": {
             "secretsProvider": "SystemAndEnvSecretStore-1",
             "purposes": [{
               "secretId": "signing.key.secret.id",
               "keyUsage": "SIGN"
             }]
           }
         }
       }
     }
   }
   ```

   Source: [jwksethandler.json](../_attachments/config/routes/jwksethandler.json)

   Notice the following features of the route:

   * The route matches requests to `/jwksethandler`.

   * The JWT signing key is managed by the SysEnvStoreSecretStore in the heap, which refers to the SecretKeyPropertyFormat for the secret's format.

   * The JwtBuilderFilter `signature` property refers to the JWT signing key in the SysEnvStoreSecretStore.

   * The JwkSetHandler refers to the JWT signing key.

3. Go to <https://ig.example.com:8443/jwksethandler>.

   The signing key is displayed as an array, as follows:

   ```json
   {
     "keys": [
       {
         "k": "cGFzc3dvcmQ",
         "kid": "signing.key.secret.id",
         "kty": "oct",
         "use": "sig"
       }
     ]
   }
   ```

   The JWK set secret is ULR base64-encoded. Although the secret is set with the value `cGFzc3dvcmQ=`, the value `cGFzc3dvcmQ` is exposed.

## More information

[org.forgerock.openig.handler.JwkSetHandler](../_attachments/apidocs/org/forgerock/openig/handler/JwkSetHandler.html)
