Test signing key rotation: JWKS caching and unknown kid
An app may validate tokens correctly until its identity provider changes keys. Rotate one HeyIdentity configuration on demand to test that your app refreshes JWKS and handles an unfamiliar key ID.
Set it up (Pro)
- Open your configuration through your owner session, and activate Pro. Enterprise and Vetted tenants also have rotation. Scratchpads cannot rotate.
- Sign in to your app once and save a token for your test. Note the token header's
kid, and the JWKS URI under All endpoints and IDs. - In Signing keys, choose Rotate key and confirm. The new key signs tokens immediately. The previous key stays published for 1 hour by default; an older retiring key is removed.
- Sign in again. The new token has a new
kid. Your app should refresh JWKS when it sees that unknown ID, then accept the new token. The previous token should still validate while its key is published.
Test an immediate cut-over
Choose Rotate without overlap and confirm. Every earlier key disappears from JWKS immediately, including a key still retiring from your previous test. New tokens have another new kid. HeyIdentity's userinfo returns 401 with invalid_token in WWW-Authenticate for earlier access tokens, and sign-out ignores an earlier id_token_hint. Authorization codes and refresh tokens keep working and produce tokens with the new key.
A client that already cached an earlier public key may keep accepting its tokens until its own cache or token expires. Removing a key from JWKS cannot erase a relying party's cache. Test with refreshed metadata as well as your app's normal cache behavior.
From CI or an agent
Reading keys works on every plan. Send the tenant's agent bearer token to the API host:
GET /agent/v1/configurations/{configuration_id}/signing-keys
POST /agent/v1/configurations/{configuration_id}/signing-keys/rotate
Content-Type: application/json
Authorization: Bearer <agent token>
{ "overlap": false }
The response's data.current_kid and data.keys identify the published keys, their current or retiring status, source and expiry. No private material is returned. MCP provides list_signing_keys and rotate_signing_key over the same operations. See the agent guide.
What to check
- Both token headers and JWKS change for this configuration only. Tenant-shaped and Microsoft Entra-shaped routes use the same keys.
- At most the current and previous key are published. A second overlap rotation drops the oldest key immediately.
- An app that pins one key should fail this test. Check that your library discovers JWKS and refreshes on an unknown
kid. - A plan ending keeps the current generated key signing; only new owner or agent rotations are refused.
Limits and refusals
Owner and agent rotations share a limit of 10 per hour per configuration. The owner card says when to retry; agents get rate_limited and Retry-After. A tenant without Pro gets plan_required; an Unverified tenant is told to claim first, then activate Pro. See all limits. Each explicit rotation is recorded in the audit log.