Describe the bug
After rotating JWT Signing Keys (asymmetric, ES256) on a Supabase project, GoTrue rejects access tokens signed under the newly-rotated key with 401 invalid JWT: unable to find matching key — even though the kid in the token header is present in the current /auth/v1/.well-known/jwks.json response. GoTrue appears to cache the JWKS in memory at process start and does not pick up a newly-rotated key without a restart/redeploy of the auth service.
To Reproduce
- Enable JWT Signing Keys on the project and rotate to a new ES256 key pair, without revoking the prior key.
- Mint a session under the new
kid via supabase.auth.signInWithPassword.
- Call any GoTrue-verified endpoint (e.g.
/auth/v1/user) with that access token.
Expected behavior
The endpoint should verify successfully since the kid is present in the current JWKS response.
Actual behavior
GoTrue returns 401 invalid JWT: unable to find matching key, because its in-memory JWKS cache was populated at process start and isn't invalidated/refreshed when keys are rotated, so newly-minted sessions under the new key fail verification until the auth service is restarted/redeployed.
Workaround in use
After any signing-key rotation: wait for the JWKS cache TTL to expire (or bounce the auth service) before issuing new sessions, and keep the previous key active (not revoked) for one full rotation cycle so in-flight sessions signed under it keep verifying.
Context
Found during an SSO build against a Supabase project with JWT Signing Keys enabled (asymmetric ES256). Filed on behalf of the project owner — happy to provide further repro details or project-level logs on request.
Describe the bug
After rotating JWT Signing Keys (asymmetric, ES256) on a Supabase project, GoTrue rejects access tokens signed under the newly-rotated key with
401 invalid JWT: unable to find matching key— even though thekidin the token header is present in the current/auth/v1/.well-known/jwks.jsonresponse. GoTrue appears to cache the JWKS in memory at process start and does not pick up a newly-rotated key without a restart/redeploy of the auth service.To Reproduce
kidviasupabase.auth.signInWithPassword./auth/v1/user) with that access token.Expected behavior
The endpoint should verify successfully since the
kidis present in the current JWKS response.Actual behavior
GoTrue returns
401 invalid JWT: unable to find matching key, because its in-memory JWKS cache was populated at process start and isn't invalidated/refreshed when keys are rotated, so newly-minted sessions under the new key fail verification until the auth service is restarted/redeployed.Workaround in use
After any signing-key rotation: wait for the JWKS cache TTL to expire (or bounce the auth service) before issuing new sessions, and keep the previous key active (not revoked) for one full rotation cycle so in-flight sessions signed under it keep verifying.
Context
Found during an SSO build against a Supabase project with JWT Signing Keys enabled (asymmetric ES256). Filed on behalf of the project owner — happy to provide further repro details or project-level logs on request.