fixmint
ES

Qué contiene un JWT y por qué decodificar no es verificar

Por · · 4 min de lectura

Un JSON Web Token (JWT) son tres fragmentos de texto unidos por puntos: un encabezado, una carga útil y una firma. Los dos primeros solo están codificados, no cifrados, así que cualquiera que tenga el token puede leerlos. La firma permite a un servidor comprobar que una parte de confianza emitió el token y que nadie lo modificó. Decodificar un token te dice lo que afirma. Solo verificarlo te dice si debes creerlo.

Decodificador de JWT¿Token caducado o válido?Úsalo gratis

Las tres partes

Un token tiene este aspecto: header.payload.signature. La primera parte del conocido token de ejemplo de jwt.io es:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Cada una de las dos primeras partes es JSON convertido a base64url, una forma de texto segura para URL. La primera parte se decodifica en:

{"alg":"HS256","typ":"JWT"}

La carga útil del mismo ejemplo se decodifica en:

{"sub":"1234567890","name":"John Doe","iat":1516239022}

La carga útil contiene las afirmaciones (claims), es decir, enunciados sobre el usuario o la sesión. La firma se calcula a partir de las dos primeras partes y una clave, así que cambiar un solo carácter hace que deje de coincidir. Base64url no necesita clave para revertirse, por lo que nunca pongas una contraseña, una clave privada ni datos personales en la carga útil.

Afirmaciones registradas

La RFC 7519, el estándar de los JWT, reserva algunos nombres cortos de afirmaciones:

  • iss (emisor): quién creó el token.
  • sub (sujeto): a quién se refiere el token, normalmente un ID de usuario.
  • aud (audiencia): el servicio para el que está pensado el token.
  • exp (caducidad): el momento a partir del cual el token deja de ser válido.
  • nbf (no válido antes de): el momento más temprano en que el token es válido.
  • iat (emitido en): cuándo se creó el token.

Los tiempos son segundos desde el 1 de enero de 1970 UTC, lo que se llama tiempo Unix. El ejemplo no tiene exp, así que según el estándar nunca caduca. Un token real debería tenerlo. Otros nombres, como role o email, pertenecen a la aplicación.

Decodificar no es verificar

Decodificar divide el token por los puntos, revierte el base64url y lee el JSON. Muestra lo que afirma el token, y lo mismo hace con un token falsificado, porque cualquiera puede escribir cualesquiera afirmaciones con cualquier firma.

Verificar recalcula la firma con la clave correcta y comprueba que coincide. También comprueba que exp y nbf encierran la hora actual, y que iss y aud son los valores que espera el servicio. Una app que lee una afirmación role sin verificar confía en quien escribió el token. Es un error muy común.

HS256, RS256 y ES256

El valor de alg indica el método. Hay tres comunes:

  • HS256 es HMAC con SHA-256. Un único secreto compartido firma y verifica, así que el secreto debe permanecer en el servidor que emite los tokens.
  • RS256 es una firma RSA con SHA-256. El emisor firma con una clave privada, y cualquiera con la clave pública puede verificar. Otros servicios pueden comprobar los tokens sin poder crearlos.
  • ES256 es una firma ECDSA con la curva P-256 y SHA-256. Funciona como RS256 con claves y firmas más pequeñas.

Usa HS256 cuando un mismo servicio emite y comprueba sus tokens. Usa RS256 o ES256 cuando otros servicios deben comprobar tokens que no emitieron.

Problemas que surgen de confiar en el encabezado

El encabezado lo escribe quien envía el token, así que el verificador no debe dejar que elija las reglas.

  1. alg: none. Un token sin firma puede declarar "alg":"none". Algunas bibliotecas llegaron a aceptar esos tokens y saltarse la comprobación. Define tú en tu código los algoritmos permitidos, nunca los tomes del token.
  2. Confusión de algoritmos. Un servidor espera RS256 y tiene una clave pública. Un atacante envía un token HS256 firmado con esa clave pública como secreto HMAC. Un verificador que acepta el algoritmo que indique el encabezado lo admite. Vincula cada clave a exactamente un algoritmo.
  3. Secretos débiles. El atacante tiene el encabezado, la carga útil y la firma, así que puede probar secretos candidatos sin conexión. Un secreto corto o una palabra común cae rápido con una lista de este tipo. La RFC 7518 dice que una clave HS256 debe tener al menos 256 bits y ser aleatoria.

Pegar un token de producción en un sitio web

Un token válido y no caducado funciona para quien lo tenga, hasta que caduque. Trátalo como una contraseña. Antes de pegarlo en un sitio, averigua si el sitio lo envía a un servidor. Una herramienta que se ejecuta por completo en la pestaña del navegador no necesita hacerlo. Puedes comprobar cualquier página observando sus peticiones de red en las herramientas de desarrollo del navegador.

Normalmente los tokens no se pueden revocar antes de caducar, salvo que el servidor mantenga una lista. Si se filtra un token activo, pide al servicio que revoque la sesión o que rote sus claves. Usa un token del entorno de pruebas para depurar siempre que puedas. Decodificador de JWT lee las tres partes en la pestaña de tu navegador, y nada de lo que pegas se envía a ningún sitio.

Webhooks: la misma idea con un secreto compartido

La mayoría de proveedores de webhooks envían en una cabecera un HMAC del cuerpo de la petición, calculado con un secreto que compartes con ellos. Tu receptor calcula el mismo HMAC y compara los dos. Los fallos habituales son pequeños. El JSON se vuelve a formatear antes de calcular el hash, así que cambian los bytes. El secreto de prueba se usa con tráfico real. O las firmas se comparan con una igualdad de cadenas normal, lo que puede filtrar información de tiempos. Usa una comparación de tiempo constante.

Verificador de firma de webhook calcula la firma a partir del secreto y el cuerpo que pegues, para GitHub, Stripe, Slack, Shopify o cualquier esquema HMAC, para que veas si los dos valores coinciden.

Respuestas rápidas

¿Está cifrado un JWT?

No. Un JWT estándar está firmado, y cualquiera puede leer su encabezado y su carga útil. Solo la firma lo protege frente a modificaciones.

¿Qué pasa si edito la carga útil?

La firma deja de coincidir, así que un servidor que verifique rechazará el token. Leer las afirmaciones no comprueba la firma, por lo que el decodificador seguirá mostrando tu versión editada.

Traducido del Original en inglés con ayuda de IA.

Comentarios

    Aún no hay comentarios. Sé el primero.

    Tu valoración (opcional)

    Tu correo nunca se muestra ni se guarda.

    Portada de Agentic AI in the BrowserAgentic AI in the Browser

    Casos de uso para flujos de trabajo con IA en el navegador que priorizan la privacidad: la misma idea de hacerlo en tu propio dispositivo en la que se basa fixmint.

    $4.99Consíguelo en GumroadEn inglés