Cuando aparece kid not found, un identificador de clave desconocido o una firma falla después de una rotación, empiezo por el header. kid suele ser la pista que permite seleccionar una clave dentro de un JWK Set de confianza.
Mi objetivo no es hacer que el token verifique “como sea”. Quiero demostrar que seleccioné la clave correcta del issuer correcto usando un algoritmo que mi aplicación permite.
Si tengo JWT y JWKS, uso JWKS Validator primero.
Paso 1: leo kid
{
"alg": "RS256",
"typ": "JWT",
"kid": "2026-09-key-03"
}
RFC 7515 y RFC 7517 definen kid como Key ID y lo usan para seleccionar claves, especialmente durante una rotación.
Para mí es una pista de selección, no una prueba. Un token no confiable puede escribir cualquier kid.
Paso 2: busco dentro de un JWKS de confianza
{
"keys": [
{ "kty": "RSA", "kid": "2026-09-key-03", "use": "sig", "alg": "RS256", "n": "...", "e": "AQAB" },
{ "kty": "RSA", "kid": "2026-06-key-02", "use": "sig", "alg": "RS256", "n": "...", "e": "AQAB" }
]
}
No busco ese kid por Internet. No es globalmente único y encontrar una clave pública con la misma etiqueta no establece confianza.
Mi cadena de confianza es:
issuer configurado
↓
metadata de confianza
↓
jwks_uri de confianza
↓
JWK Set
↓
coincidencia de kid
Paso 3: si falta kid
No todos los JWT firmados están obligados a llevarlo.
Si el JWKS de confianza tiene una sola clave compatible, la política puede permitir una selección no ambigua.
Si hay varias:
{
"keys": [
{ "kty": "RSA", "kid": "key-a", "alg": "RS256" },
{ "kty": "RSA", "kid": "key-b", "alg": "RS256" }
]
}
y el header solo dice RS256, no quiero “probar claves hasta que una pase” sin una regla determinista.
JWKS Validator también reporta una selección ambigua en ese caso.
Paso 4: reviso alg, kty, use, key_ops
Una coincidencia de kid no termina el trabajo.
Compruebo:
- JWT
alg; - JWK
kty; - JWK
algsi está presente; usesi está presente;key_opssi está presente.
RS256 necesita una clave RSA para verificación; ES256 necesita una clave EC/P-256. Si use dice enc, no uso esa clave para una firma JWS.
Paso 5: kid not found suele llevarme a la rotación
issuer publica clave A
→ los tokens usan A
→ issuer añade B
→ nuevos tokens usan kid B
→ el verificador conserva caché con solo A
Entonces reviso:
- si el issuer publica B ahora;
- TTL de caché;
- refresco ante un
kidausente; - si estoy consultando el entorno o tenant equivocado.
No elimino la caché para hacer una petición de red por cada token; uso una estrategia de refresco controlada.
Paso 6: entorno y tenant
JWT iss: https://login.dev.example.com/
API trusts: https://login.example.com/
explica perfectamente un kid not found.
Por eso pregunto tanto “¿dónde está la clave?” como “¿este token viene del issuer que pretendía confiar?”.
La guía de validación de issuer ayuda aquí.
Paso 7: no sigo jku o x5u automáticamente
Son valores controlados por la entrada. RFC 8725 advierte sobre fallos de confianza y SSRF al seguir URLs arbitrarias.
JWKS Validator solo carga una URL que yo introduzco explícitamente; no confía automáticamente en la que sugiera el token.
Paso 8: encontrar kid no significa verificar la firma
kid encontrado ✓
algoritmo compatible ✓
clave para firma ✓
firma verificada ✓ / ✕
Si los primeros controles pasan pero la firma falla, sigo la guía de firma inválida.
Paso 9: después de la firma todavía valido claims
Reviso iss, aud, exp, nbf, tipo de token y permisos. Una firma correcta no garantiza que el token sea para esta API.
Mi checklist de kid
- Decodifico el JWT y leo
alg,kid,iss. - Identifico el issuer de confianza.
- Obtengo su JWKS de confianza.
- Busco una coincidencia exacta de
kid. - Reviso
kty,alg,use,key_ops. - Si falta la clave, reviso rotación y caché.
- Reviso entorno y tenant.
- No confío en URLs de claves controladas por el token.
- Verifico la firma con la JWK seleccionada.
- Valido issuer, audience y tiempo.
La idea clave: kid me ayuda a encontrar una clave; no me dice si debo confiar en ella.