JWT explicado: estructura, algoritmos y errores de seguridad comunes

Los JWT son el estándar para autenticación sin estado — pero tienen riesgos de seguridad sutiles. Aprende cómo funcionan y qué puede salir mal.

Un JSON Web Token (JWT, pronunciado "jot") es un formato de token compacto y seguro para URLs definido por el RFC 7519. Es el mecanismo estándar para autenticación sin estado en APIs REST — el servidor emite un token firmado, y el cliente lo presenta en cada solicitud subsiguiente. El servidor verifica la firma y confía en los claims sin consultar una base de datos de sesiones.

Estructura de un JWT

Todo JWT tiene exactamente tres segmentos separados por puntos, cada uno codificado en Base64url: header.payload.signature.

  • El Header es un objeto JSON que declara el tipo de token ("JWT") y el algoritmo de firma, como HS256 (HMAC-SHA256) o RS256 (RSA con SHA-256).
  • El Payload contiene "claims" — pares clave-valor sobre el usuario o sesión. Los claims estándar incluyen sub (identificador del usuario), iss (emisor), exp (expiración como timestamp UNIX) y iat (emitido en). Los claims personalizados pueden llevar roles, permisos o cualquier dato específico de la aplicación.
  • La Signature se calcula a partir del header y payload usando el algoritmo y la clave. Garantiza que el token no fue modificado después de ser emitido.

Simétrico vs. Asimétrico

HS256 (HMAC-SHA256) usa una única clave compartida para firmar y verificar. RS256 y ES256 usan pares de claves asimétricas: la clave privada firma, la pública verifica. RS256 es preferible en microservicios donde múltiples servicios necesitan verificar tokens sin compartir un secreto.

La vulnerabilidad "Algorithm None"

En 2015 se descubrió que muchas librerías JWT aceptaban el valor none en el header, lo que significa que el token no lleva firma. Un atacante podía falsificar cualquier claim configurando {"alg": "none"} y omitiendo la firma. La defensa: especifica siempre el algoritmo esperado explícitamente al verificar — nunca confíes en el algoritmo declarado en el token.

Expiración y revocación

El claim exp define un timestamp después del cual el token debe ser rechazado. Tiempos de expiración cortos (15–60 minutos) limitan el daño si un token es robado. La limitación fundamental de los JWT es que no pueden revocarse antes de expirar sin estado en el servidor. Si necesitas revocación instantánea, usa tokens de vida corta más un mecanismo de refresh token, o mantén una lista de bloqueo de tokens.

Qué no poner en el payload

El payload JWT está firmado, no cifrado. Cualquiera que tenga el token puede decodificar y leer el payload — solo está codificado en Base64url. Nunca incluyas datos sensibles como contraseñas, números de tarjeta o información que no deba ser visible al cliente. La firma solo garantiza que el payload no fue alterado, no que sea confidencial.

Decodificar JWTs para depuración

Durante el desarrollo, poder decodificar un JWT rápidamente para inspeccionar sus claims y verificar la expiración es invaluable. Un decodificador en el navegador procesa el token completamente en local — sin solicitud de red, sin riesgo de que el token quede registrado en un servidor externo.