Mensaje de error
failed to verify signature: failed to verify id token signature
También se muestra como
- failed to verify signature: fetching keys oidc: get keys failed
Cuando falla la propia solicitud del JWKS, el texto es «failed to verify signature: fetching keys oidc: get keys failed …», seguido del error HTTP o de red.
coreos/go-oidc (Go) — IDTokenVerifier.Verify with a RemoteKeySet
Qué significa
go-oidc descargó el conjunto de claves del proveedor (con una segunda descarga si el `kid` era desconocido) y ninguna clave publicada verificó la firma del token. go-oidc no distingue entre «no hay ninguna clave con este kid» y «hay una clave con este kid, pero la firma no coincide»: en ambos casos, el token no se firmó con una clave que este proveedor publique actualmente. Si no se pudo descargar el conjunto de claves en absoluto, el mensaje continúa con «fetching keys …».
Por qué ocurre
El token procede de otro proveedor o de otro inquilino
frecuenteUn token de un inquilino de preproducción, de otro realm o directamente de otro proveedor de identidad. Comprueba `iss` en la carga útil antes de sospechar de las claves.
El verificador descarga un conjunto de claves equivocado
frecuenteUna URL de `NewRemoteKeySet` configurada a mano que apunta a las claves de otro inquilino, o un proxy o una caché que sirve un JWKS desactualizado después de una rotación.
ID de clave reutilizados entre claves distintas
ocasionalLos emisores que reutilizan un `kid` para una clave nueva (por ejemplo, un nombre fijo por entorno) generan tokens cuyo `kid` coincide con una clave publicada que no es la clave de firma.
Se modificó el token
ocasionalCualquier cambio en el encabezado o en la carga útil después de firmar —incluso volver a codificarlos— invalida la firma.
Cómo solucionarlo
- 1.
Crear el verificador a partir del descubrimiento
`provider.Verifier` usa el `jwks_uri` del documento de descubrimiento del proveedor y el emisor del proveedor, con lo que las URL configuradas a mano dejan de ser una fuente de discrepancias.
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 el kid del token con las claves publicadas
Si el `kid` no está publicado, el token es ajeno o el proveedor no ha terminado una rotación. Si está publicado, la clave que hay detrás no firmó 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}'