Pegá un JSON Web Token para inspeccionar su header, payload y firma — 100% en tu navegador con Web Crypto, nunca se manda a ningún servidor.
Qué contiene cada segmento de un token, en qué se diferencian HS256, RS256 y ES256, y qué comprobaciones exige el RFC 8725.
Un JWT en serialización compacta (JWS, RFC 7515) son tres cadenas Base64URL sin padding separadas por puntos: cabecera.payload.firma. La cabecera declara "alg" y, opcionalmente, "kid" para identificar la clave dentro de un JWKS. El payload transporta los claims registrados de la sección 4.1 del RFC 7519: "iss", "sub", "aud", "exp", "nbf", "iat" y "jti". Los tres temporales usan el tipo NumericDate, es decir segundos Unix y no milisegundos: pasar Date.now() sin dividir entre 1000 genera tokens que expiran en el año 57000 y que ningún validador rechazará. La firma cubre exactamente la cadena ASCII "base64url(header).base64url(payload)", así que reescribir el JSON con otro orden de claves o con otra indentación ya invalida el token.
HS256 calcula un HMAC-SHA-256 con un secreto compartido, de modo que quien puede verificar también puede emitir. Es razonable en un monolito que firma y valida sus propias sesiones, siempre con una clave aleatoria de al menos 256 bits: el RFC 7518 exige que la clave HMAC tenga como mínimo el tamaño de la salida del hash. RS256 firma con RSASSA-PKCS1-v1_5 y una clave privada de 2048 bits o más, y los consumidores solo necesitan la pública, habitualmente publicada en /.well-known/jwks.json. ES256 (ECDSA sobre la curva P-256) da seguridad equivalente con firmas de 64 bytes frente a los 256 bytes de RSA-2048, algo relevante cuando el token viaja en cada cabecera Authorization.
El RFC 8725 recopila los fallos que más se repiten en producción. Con "alg": "none" el atacante entrega un token sin firma y el validador lo acepta porque confía en una cabecera que él mismo controla; la defensa es fijar en el servidor una lista blanca de algoritmos. La confusión de algoritmo cambia RS256 por HS256 y firma usando la clave pública RSA como secreto HMAC, algo posible en librerías antiguas que recibían un único parámetro "key". La inyección por "jku", "x5u" o "kid" desvía la resolución de claves hacia un host o una ruta del atacante: hay que limitar "kid" a un conjunto conocido y nunca seguir URLs que vengan en la cabecera. Validar también "iss" y "aud" impide reutilizar un token legítimo de otro servicio.
No de forma nativa: un JWS es autocontenido y el validador no consulta ningún estado. Los patrones habituales son un "exp" corto de 5 a 15 minutos acompañado de un refresh token opaco guardado en base de datos, una lista de denegación indexada por "jti" con TTL igual al del token, o un contador de versión de credenciales incluido como claim que se incrementa al cerrar sesiones.
JWS (RFC 7515) firma el payload pero lo deja legible: cualquiera que tenga el token puede decodificar el Base64URL y leer los claims. JWE (RFC 7516) cifra el contenido y tiene cinco segmentos en lugar de tres, con una cabecera que añade "enc" (por ejemplo A256GCM) junto a "alg". Si el payload lleva datos que no deben verse, hace falta JWE o simplemente no incluirlos.
Porque la verificación se hace sobre los bytes exactos de los dos primeros segmentos, no sobre el objeto JSON resultante. Decodificar, reformatear y volver a codificar cambia espacios, orden de claves o padding "=" y produce una entrada distinta para el HMAC. También falla si el secreto tiene espacios invisibles al final o si la clave pública PEM se pegó sin las líneas BEGIN y END.
Decodificá segmentos Base64URL sueltos de una cabecera o un payload.
Abrir herramienta →AUTHSecretos HMAC aleatorios de 256 bits o más para firmar con HS256.
Abrir herramienta →DATAIdentificadores únicos para el claim "jti" y la trazabilidad de sesiones.
Abrir herramienta →