Skip to content

RP keys and rotation

View as Markdown

RP keys prove the client’s identity at /token and verify its signed Request Objects. They are separate from the provider keys that sign ID Tokens and from application keys that sign access tokens. See token verification.

Source Configure RP keeps
Platform client-auth key Select the platform key source for a managed client. The client-auth private key supplied at creation or rotation.
Inline RP JWKS Register a JSON jwks object containing public RSA signing keys. The corresponding private keys.
RP JWKS URI Register an HTTPS jwks_uri that serves a public JWKS. The corresponding private keys and the HTTPS endpoint.

Verification uses the selected source only. A failed RP key lookup or signature never falls back to the platform client-auth key. Dynamic registration with private_key_jwt requires either jwks or jwks_uri.

For a dynamically registered client, open its Application OIDC page in With and follow the organization OIDC client management link. An organization OWNER can select the source and save the public-key configuration there. If the page changed during your edit, reload the current configuration before saving again.

Run this Node.js example in a protected backend working directory. It creates a new key pair. It fails if rp-private.pem already exists, so it cannot replace an existing private key by accident.

import { generateKeyPairSync } from 'node:crypto';
import { writeFileSync } from 'node:fs';
const { privateKey, publicKey } = generateKeyPairSync('rsa', {
modulusLength: 2048,
});
writeFileSync('rp-private.pem', privateKey.export({
format: 'pem',
type: 'pkcs8',
}), { mode: 0o600, flag: 'wx' });
const jwk = publicKey.export({ format: 'jwk' });
const jwks = { keys: [{
...jwk,
kid: 'rp-signing-1',
alg: 'RS256',
use: 'sig',
key_ops: ['verify'],
}] };
writeFileSync('rp-public-jwks.json', JSON.stringify(jwks, null, 2), {
flag: 'wx',
});

Register the contents of rp-public-jwks.json inline, or serve them from your HTTPS JWKS URI. Never publish rp-private.pem.

Each public key must be RSA with a modulus of at least 2048 bits. Use RS256. Private JWK fields such as d, p, and q are rejected. A JWKS can contain at most 16 keys. Use a distinct nonempty kid for each key and put that kid in signed JWT headers. If the JWT has no kid, exactly one key must be available.

Use the selected source’s private key to sign an RS256 JWT. Send it with the standard client_assertion_type and client_assertion form fields at /token.

Claim Value
iss, sub Your client_id.
aud The exact discovered token_endpoint URL. The bare issuer is not accepted.
iat Current epoch time in seconds. Keep the backend clock synchronized.
exp After iat, no more than 300 seconds later.
jti A fresh value for every assertion. Never reuse an assertion.

Client assertions and Request Objects are different JWTs. See the token exchange and the signed request example.

For a planned rotation, keep the same key-source type:

  1. Generate the replacement with a new kid. Keep the current public key in the JWKS and add the replacement.
  2. For inline JWKS, save the combined set in With. For a JWKS URI, publish the combined set before signing with the replacement. The provider caches remote RP keys for up to 60 seconds and rate-limits refreshes for unknown kid values.
  3. Start signing new assertions and Request Objects with the replacement. Confirm new requests succeed.
  4. Remove the old public key after requests signed with it have completed or expired. Save the new inline set or update the HTTPS document.

Do not switch source types as part of a routine key rotation. Source changes and key edits can invalidate an authorization already in progress. Start a fresh authorization when that happens.

For a suspected private-key leak, remove the compromised public key promptly, update backend signing, and review affected client sessions. Remote caches can retain the old public key for their remaining cache lifetime. If the client must stop immediately, use application lifecycle controls.

Rotating an RP key does not rotate the provider’s ID Token key or your application’s access-token signing keys.