Mensagem de erro
failed to verify signature: failed to verify id token signature
Também aparece como
- failed to verify signature: fetching keys oidc: get keys failed
Quando a própria requisição ao JWKS falha, o texto é “failed to verify signature: fetching keys oidc: get keys failed …”, seguido do erro HTTP ou de rede.
coreos/go-oidc (Go) — IDTokenVerifier.Verify with a RemoteKeySet
O que significa
O go-oidc baixou o conjunto de chaves do provedor (buscando de novo uma vez se o `kid` era desconhecido), e nenhuma chave publicada conseguiu verificar a assinatura do token. O go-oidc não distingue “nenhuma chave com este kid” de “uma chave com este kid, mas com a assinatura errada” — os dois casos significam que o token não foi assinado por uma chave que este provedor publica atualmente. Se o conjunto de chaves nem sequer pôde ser buscado, a mensagem continua, em vez disso, com “fetching keys …”.
Por que acontece
O token vem de outro provedor ou locatário
comumUm token de um locatário de homologação, de outro realm ou de um provedor de identidade completamente diferente. Confira o `iss` no payload antes de suspeitar das chaves.
O verificador busca o conjunto de chaves errado
comumUma URL de `NewRemoteKeySet` configurada à mão que aponta para as chaves de outro locatário, ou um proxy/cache que serve um JWKS desatualizado depois de uma rotação.
IDs de chave reutilizados em chaves diferentes
ocasionalEmissores que reutilizam um `kid` para uma chave nova (por exemplo, um nome fixo por ambiente) produzem tokens cujo `kid` corresponde a uma chave publicada que não é a chave de assinatura.
O token foi modificado
ocasionalQualquer alteração no cabeçalho ou no payload depois da assinatura — inclusive uma nova codificação — invalida a assinatura.
Como corrigir
- 1.
Criar o verificador a partir da descoberta
O `provider.Verifier` usa o `jwks_uri` do documento de descoberta do provedor e o emissor do provedor, o que elimina URLs configuradas à mão como fonte de divergência.
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.
Comparar o kid do token com as chaves publicadas
Se o `kid` não está publicado, o token não é deste provedor ou o provedor ainda não concluiu uma rotação. Se está publicado, a chave correspondente não assinou este 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}'