Error message
failed to verify signature: failed to verify id token signature
Also printed as
- failed to verify signature: fetching keys oidc: get keys failed
When the JWKS request itself fails, the text is "failed to verify signature: fetching keys oidc: get keys failed …" followed by the HTTP or network error.
coreos/go-oidc (Go) — IDTokenVerifier.Verify with a RemoteKeySet
What it means
go-oidc downloaded the provider's key set (refetching once if the `kid` was unknown) and no published key verified the token's signature. go-oidc does not distinguish "no key with this kid" from "a key with this kid but the wrong signature" — both mean the token was not signed by a key this provider currently publishes. If the key set could not be fetched at all, the message continues with "fetching keys …" instead.
Why it happens
The token comes from another provider or tenant
commonA token from a staging tenant, a different realm, or a different identity provider entirely. Check `iss` in the payload before suspecting keys.
The verifier fetches the wrong key set
commonA hand-configured `NewRemoteKeySet` URL that points at another tenant's keys, or a proxy/cache serving an outdated JWKS after a rotation.
Key IDs reused across keys
occasionalIssuers that reuse a `kid` for a new key (for example a fixed name per environment) produce tokens whose `kid` matches a published key that is not the signing key.
The token was modified
occasionalAny change to the header or payload after signing — including re-encoding — invalidates the signature.
How to fix it
- 1.
Build the verifier from discovery
`provider.Verifier` uses the `jwks_uri` from the provider's discovery document and the provider's issuer, which removes hand-configured URLs as a source of mismatch.
go provider, err := oidc.NewProvider(ctx, "https://accounts.example.com") // discovery gives the right jwks_uri if err != nil { return err } verifier := provider.Verifier(&oidc.Config{ClientID: clientID}) idToken, err := verifier.Verify(ctx, rawIDToken) - 2.
Compare the token's kid with the published keys
If the `kid` is not published, the token is foreign or the provider has not finished a rotation. If it is published, the key behind it did not sign this token.
bash # kid in the token header vs kids the provider publishes python3 -c 'import base64,json,sys; h=sys.argv[1].split(".")[0]; print(json.loads(base64.urlsafe_b64decode(h+"="*(-len(h)%4))))' "$ID_TOKEN" curl -s "$(curl -s https://accounts.example.com/.well-known/openid-configuration | jq -r .jwks_uri)" | jq '.keys[] | {kid, alg, kty}'