skip to content

What is a JWKS endpoint, and what does a resource server do with the keys it returns?

level: middleimportance: must knowfreq 62%

answer

  1. A published set of public keys
  2. JSON object with a keys array
  3. kid picks one of many
  4. Fetch once, cache, refresh carefully
  5. Never take the key from the token

basics

~20 s

A JWKS endpoint serves a JSON Web Key Set: a JSON document with a keys array of public keys in JWK form. A verifier fetches it over HTTPS, caches it, selects the key matching the token's kid, and verifies the signature with that key.

solid answer

~50 s

A **JWKS** — JSON Web Key Set, defined in RFC 7517 — is a JSON document of the shape `{"keys":[ ... ]}`, where each entry is a JWK describing one public key: `kty` for the key type (`RSA`, `EC`, `OKP`), `kid` as its identifier, `use` of `sig` for signing keys, an optional `alg`, and the public parameters themselves (`n` and `e` for RSA, `crv`/`x`/`y` for EC). Issuers publish it at a stable HTTPS URL, commonly advertised as `jwks_uri` in the issuer's discovery document. A resource server fetches that set once, caches it, and on each token reads the header's `kid`, picks the matching key, checks it is the right type for the algorithm it expects, and verifies. Two operational rules matter: cache with a bounded TTL and refresh on an unknown `kid` with rate limiting, and never fetch a key from a URL the token itself supplies.

code

json · 21 lines
json
{
  "keys": [
    {
      "kty": "RSA",
      "kid": "auth-2026-06",
      "use": "sig",
      "alg": "RS256",
      "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbW...",
      "e": "AQAB"
    },
    {
      "kty": "EC",
      "kid": "auth-2026-08",
      "use": "sig",
      "alg": "ES256",
      "crv": "P-256",
      "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
      "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
    }
  ]
}

go deeper

for a junior

Recall that a JWKS is a published set of public keys in JSON form and that a verifier picks one by the token's key identifier.

for a middle

Explain the document's members — kty, kid, use, alg, and the public parameters — and the fetch, cache, select, verify sequence.

for a senior

Cover the operational behaviour: bounded caching, rate-limited refresh on unknown identifiers, and serving from the last good copy when the issuer is unreachable.

for a principal

Own the dependency you have created — every protected API now relies on the issuer's key endpoint, so decide on caching policy, failure behaviour, and blast radius before adopting it fleet-wide.

## The problem a JWKS solves Asymmetric signing only helps if every verifier can obtain the issuer's current public key without a manual step. Baking a PEM file into each service's configuration works exactly once; the day the issuer rotates, every service needs a redeploy. A JWKS makes the key set a document the issuer publishes and verifiers read at runtime. ## The document RFC 7517 defines a JWK as a JSON object describing one key, and a JWK Set as an object with a `keys` member holding an array of them. The members you will see on a signing key: - `kty` — key type: `RSA`, `EC`, `OKP`, or `oct` for symmetric keys. - `kid` — an opaque key identifier, matched against the token header's `kid`. - `use` — `sig` for signature keys, `enc` for encryption keys. - `alg` — the algorithm this key is intended for, such as `RS256` or `ES256`. - `key_ops` — an alternative, finer-grained statement of permitted operations. - The public parameters: `n` (modulus) and `e` (exponent) for RSA, encoded Base64url; `crv`, `x`, and `y` for EC keys. A JWKS for signature verification must contain only public key material. A `kty` of `oct` carries a symmetric key in the `k` member — publishing that would hand out the signing secret, so it never belongs in a public key set. ## Locating it The URL is normally discovered rather than hard-coded per service: an issuer that supports discovery publishes a metadata document containing a `jwks_uri` member, and verifiers read the key set from there. Either way the transport is HTTPS with certificate validation — the integrity of the whole verification chain rests on having fetched the right document from the right host. ## What the verifier does with it The steady-state algorithm is small: 1. Read the token's header and take `kid`. 2. Look up that `kid` in the cached key set. 3. Check that the key's type and intended use are consistent with the algorithm the verifier is configured to accept — an `RSA` key for `RS256`, an `EC` key for `ES256`. 4. Verify the signature with that key, then proceed to claim validation. When a token arrives with a `kid` that is not in the cache, the verifier may refetch, because the issuer may have rotated. That refresh must be **rate limited** and its failures cached briefly; otherwise an attacker can send a stream of tokens carrying random `kid` values and turn every request into an outbound HTTP call to the issuer, which is both a self-inflicted denial of service and an amplifier pointed at the authorization server. ## Caching, staleness, and availability The key set is fetched over the network, so the verifier's availability now depends on it. Sensible behaviour: honour the response's cache directives with a sane floor and ceiling, refresh in the background before expiry, and on a fetch failure keep serving from the last good copy rather than rejecting every request. Failing closed on a transient network error to the issuer converts a minor blip into a total outage of every protected API. A cold start is the other edge: a freshly deployed instance has an empty cache and must fetch before it can verify anything, which is worth warming rather than discovering under load. ## Trust rules Two rules keep the mechanism sound. First, **the key source is configuration, not token content**. The `kid` selects *among keys you already trust*; it must never cause a fetch from a location the token names. The JOSE header can carry `jku`, `jwk`, and `x5u` parameters that point at or embed key material, and honouring any of them lets an attacker supply the key that verifies their own token. Second, **bind the algorithm to the key**. A verifier configured for `RS256` should reject a token whose header names a different algorithm, and should not attempt verification with a key whose type does not match. ## Symmetric setups have no JWKS If an issuer signs with `HS256`, there is nothing publishable: the verification key is the signing secret. That asymmetry is a good way to remember what a JWKS is for — it exists precisely because asymmetric verification keys are safe to hand to anyone.

  • What should a verifier do when the key-set endpoint is unreachable?
    Keep serving from the last good cached copy rather than rejecting traffic. Public keys change on a rotation schedule measured in weeks or months, so a slightly stale set is almost always correct, whereas failing closed turns a transient network problem at the issuer into a total outage across every protected API.
  • Why is it unsafe to honour the jku or jwk header parameters?
    Both let the token itself point at or embed the key used to verify it, so an attacker signs a token with a key they control and supplies that key alongside it. Verification then succeeds against attacker-chosen material. Key selection must come from configuration, with kid only choosing among keys already trusted.
  • Does an issuer signing with HS256 publish a JWKS?
    No, and it should not. With HMAC the verification key is the signing secret, so there is nothing that can safely be published. A JWKS exists because asymmetric verification keys are public by design; the absence of one is a reliable hint that an issuer is using symmetric signing.

saying these in an interview costs you the question

  • Fetches the key set on every incoming request
  • Trusts a key URL supplied by the token's header
  • Publishes symmetric keys in the key set
  • Rejects all requests when a key-set fetch fails
  • Ignores kid and tries every key in the set

context