Un JSON Web Token es una forma compacta de transportar declaraciones entre sistemas. Suele verse como tres partes separadas por puntos: header, payload y signature. Cada parte usa Base64URL, y la firma permite detectar si el token fue modificado. Esta estructura lo hizo popular para APIs y servicios distribuidos, pero también generó una idea peligrosa: pensar que un JWT válido resuelve por sí solo todo el problema de autenticación y autorización.
El header describe cómo se protege el token
El header suele indicar el algoritmo de firma y el tipo de token. Esa información ayuda al verificador a elegir la clave o el método correcto, pero no debe aceptarse de forma ingenua. El servidor debe tener una política de algoritmos permitidos y no permitir que el token elija una opción insegura.
Históricamente, errores como aceptar none o confundir algoritmos simétricos y asimétricos causaron vulnerabilidades. La validación correcta empieza antes de leer claims: primero se verifica que el método de protección sea el esperado por el sistema.
El payload contiene claims, no secretos
El payload es JSON codificado, no cifrado. Cualquiera que tenga el token puede decodificarlo y leer sus claims. Es común incluir subject, issuer, audience, expiration y algunos atributos de autorización. No se deben incluir contraseñas, datos personales innecesarios ni información que no pueda exponerse al portador.
La firma protege integridad, no confidencialidad. Si el sistema necesita ocultar claims, debe usar cifrado adecuado o evitar ponerlos en el token. Un JWT firmado es transparente por diseño.
La firma une header y payload con una clave
Para crear el token, el emisor firma la representación exacta de header y payload. El receptor recalcula o verifica esa firma con la clave correspondiente. Si un atacante cambia un claim, la firma deja de coincidir. Esta propiedad permite que servicios distintos confíen en un token emitido por una autoridad compartida.
La clave es el verdadero punto de confianza. En HMAC, emisor y verificador comparten el mismo secreto. En RSA o ECDSA, el emisor firma con private key y muchos servicios verifican con public key. El modelo de claves debe coincidir con la arquitectura.
Claims registrados evitan ambigüedad
Claims como iss, sub, aud, exp, nbf e iat existen para describir quién emitió el token, para quién es, cuándo expira y desde cuándo es válido. Un verificador serio no mira solo la firma; también valida que esos claims coincidan con el uso actual.
Un token firmado para otro audience no debería aceptarse por una API diferente. Un token expirado no debería funcionar aunque la firma sea correcta. La firma dice “esto no fue alterado”; los claims dicen “esto aplica aquí y ahora”.
La expiración limita daño, pero no revoca por arte de magia
Los JWT suelen ser stateless: el servidor no necesita consultar una sesión central en cada request. Eso mejora escalabilidad, pero dificulta revocación inmediata. Si un token se roba, puede funcionar hasta expirar, salvo que exista una lista de revocación, rotación de claves o introspection.
Por eso muchos sistemas usan access tokens cortos y refresh tokens controlados con más estado. El access token viaja a APIs; el refresh token permite obtener uno nuevo y puede revocarse con mayor precisión.
Clock skew debe estar definido
La validación de exp y nbf depende del reloj del verificador. En sistemas distribuidos, los relojes pueden diferir algunos segundos. Una pequeña tolerancia puede evitar fallos legítimos, pero una tolerancia grande extiende la vida real del token.
La política debe ser explícita y uniforme. Diferentes servicios no deberían aceptar ventanas distintas sin motivo. También conviene registrar por qué se rechazó un token: expirado, demasiado temprano, issuer incorrecto o firma inválida.
El almacenamiento del token cambia el riesgo
Un JWT en localStorage es fácil de usar desde JavaScript, pero queda expuesto a XSS. Una cookie HttpOnly reduce exposición a scripts, pero introduce consideraciones de CSRF y SameSite. No existe ubicación perfecta; el modelo debe considerar amenazas reales del producto.
La longitud del token también importa. Claims excesivos aumentan cabeceras, pueden superar límites de proxies y hacen que cada request transporte datos que quizá no son necesarios.
La depuración debe separar decodificar de confiar
Es útil decodificar un JWT para ver claims durante soporte, pero una herramienta de decodificación no valida seguridad completa. La aplicación debe verificar firma, algoritmo, issuer, audience, expiración y política de permisos. Leer el payload solo muestra lo que el token afirma.
También conviene registrar un identificador de emisión o jti cuando el modelo lo necesita. Ese identificador permite correlacionar eventos, investigar abuso y revocar tokens concretos sin almacenar el token completo en logs. Para soporte, es mejor buscar por ese identificador que pedir al usuario que copie una credencial completa.
Un JWT funciona bien cuando sus límites están claros: es un contenedor firmado de claims, no una sesión mágica ni un lugar para secretos. Con claves bien gestionadas, expiraciones razonables y validación completa, puede simplificar la comunicación entre servicios.