---
title: JwkSetSecretStore
description: A secret store of JSON Web Keys (JWK) from a local or remote JWK Set.
component: pinggateway
version: 2026
page_id: pinggateway:reference:JwkSetSecretStore
canonical_url: https://docs.pingidentity.com/pinggateway/2026/reference/JwkSetSecretStore.html
revdate: 2025-06-02T18:01:47Z
section_ids:
  JwkSetSecretStore-usage: Usage
  JwkSetSecretStore-properties: Properties
  JwkSetSecretStore-log: Log level
  JwkSetSecretStore-example: Example
  JwkSetSecretStore-moreinfo: More information
---

# JwkSetSecretStore

A secret store of JSON Web Keys (JWK) from a local or remote JWK Set.

This Secret store can only manage secrets of the [CryptoKey](../security-guide/keys.html#secret-types) type.

The secrets provider builds the secret, checking that the secret's constraints are met, and returns a unique secret. If the secret's constraints aren't met, the secrets provider cannot build the secret and the secret query fails.

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

```json
{
  "name": string,
  "type": "JwkSetSecretStore",
  "config": {
    "jwkUrl": configuration expression<url>,
    "handler": Handler reference,
    "cacheTimeout": configuration expression<duration>,
    "cacheMissCacheTime": configuration expression<duration>,
    "leaseExpiry": configuration expression<duration>
  }
}
```

## Properties

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

  A URL that contains the client's public keys in JWK format.

* `"handler"`: *Handler [reference](preface.html#definition-reference), optional*

  An HTTP client handler to communicate with the `jwkUrl`.

  Usually set this property to the name of a ClientHandler configured in the heap, or a chain that ends in a ClientHandler.

  Default: ClientHandler

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

  Delay before the cache is reloaded. The cache contains the `jwkUrl`.

  The cache cannot be deactivated. If a value lower than 10 seconds is configured, a warning is logged and the default value is used instead.

  Default: 2 minutes

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

  If the `jwkUrl` is looked up in the cache and isn't found, this is the delay before the cache is reloaded.

  Default: 2 minutes

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

  The amount of time that secrets produced by this store can be cached before they must be refreshed.

  If the duration is `zero` or `unlimited`, PingGateway issues a warning, and uses the default value.

  Default: 5 minutes

## Log level

To facilitate debugging secrets for the JwkSetSecretStore, in `logback.xml` add a logger defined by the fully qualified package name of the JwkSetSecretStore. The following line in `logback.xml` sets the log level to `ALL`:

```xml
<logger name="org.forgerock.secrets.jwkset" level="ALL" />
```

## Example

You can find an example of how to set up and use JwkSetSecretStore to validate signed access tokens in [With JwkSetSecretStore and PingAM](../gateway-guide/oauth2-rs-stateless-signed-sat.html).

In the following example, a StatelessAccessTokenResolver validates a signed access token by using a JwkSetSecretStore:

```json
"accessTokenResolver": {
  "type": "StatelessAccessTokenResolver",
  "config": {
    "secretsProvider": {
      "type": "JwkSetSecretStore",
      "config": {
        "jwkUrl": "https://am.example.com:8888/am/oauth2/connect/jwk_uri"
      },
      "issuer": "https://am.example.com:8888/am/oauth2",
      "verificationSecretId": "verification.secret.id"
    }
  }
}
```

The JWT signature is validated as follows:

* If the JWT contains a `kid` with a matching secret in the JWK set:

  * The secrets provider queries the JwkSetSecretStore for a named secret.

  * The JwkSetSecretStore returns the matching secret, identified by a stable ID.

  * The StatelessAccessTokenResolver tries to validate the signature with that named secret. If it fails, the token is considered as invalid.

  In the route, note that the property `verificationSecretId` must be configured but isn't used in named secret resolution.

* If the JWT contains a `kid` without a matching secret in the JWK set:

  * The secrets provider queries the JwkSetSecretStore for a named secret.

  * Because the referenced JWK set doesn't contain a matching secret, named secret resolution fails. PingGateway tries valid secret resolution in the same way as when the JWT doesn't contain a `kid`.

* If the JWT doesn't contain a `kid`:

  * The secrets provider queries the JwkSetSecretStore for list of valid secrets, whose secret ID is `verification.secret.id`.

  * The JwkSetSecretStore returns all secrets in the JWK set whose purpose is signature verification. For example, signature verification keys can have the following JWK parameters:

    ```json
    {
      "use": "sig"
    }
    ```

    ```json
    {
      "key_opts": [ "verify" ]
    }
    ```

    Secrets are returned in the order that they are listed in the JWK set.

  * The StatelessAccessTokenResolver tries to validate the signature with each secret sequentially, starting with the first, and stopping when it succeeds.

  * If none of the valid secrets can verify the signature, the token is considered as invalid.

## More information

[org.forgerock.openig.secrets.JwkSetSecretStoreHeaplet](../_attachments/apidocs/org/forgerock/openig/secrets/JwkSetSecretStoreHeaplet.html)

[JSON Web Key (JWK)](https://www.rfc-editor.org/rfc/rfc7517)
