Saltar al contenido

JWT

¿Qué es JWT (JSON Web Token)? La Guía Completa

5 min read

¿Qué es JWT (JSON Web Token)? La Guía Completa

Si eres un desarrollador web que crea aplicaciones modernas, especialmente aplicaciones de una sola página (SPAs) como React o Vue, o te conectas a APIs REST, es casi seguro que te hayas encontrado con JWT (a menudo pronunciado como "jot").

JWT significa JSON Web Token. Rápidamente se ha convertido en el estándar de la industria para asegurar APIs y autenticar usuarios en sistemas distribuidos. Pero, ¿cómo exactamente una cadena de caracteres aparentemente aleatorios mantiene segura toda la sesión de un usuario? ¿Por qué la industria se alejó de las cookies de sesión tradicionales hacia estos tokens?

En esta guía exhaustiva, desglosaremos la mecánica de los JSON Web Tokens, exploraremos su estructura interna, los compararemos con los métodos de autenticación tradicionales y discutiremos las prácticas de seguridad críticas que debes seguir para evitar que tus JWTs se vean comprometidos.

El Problema: Autenticación Tradicional con Estado (Stateful)

Para entender por qué se inventó JWT, debes comprender el problema que resuelve.

HTTP es un protocolo sin estado (stateless). Esto significa que cada vez que un usuario realiza una solicitud a un servidor (como hacer clic en un enlace o enviar un formulario), el servidor no tiene memoria de la solicitud anterior. Si inicias sesión (login) en la página 1, el servidor olvidará inmediatamente que estás conectado en el momento en que navegues a la página 2.

Históricamente, los desarrolladores resolvieron esto utilizando Cookies de Sesión (Session Cookies) (Autenticación con estado).

  1. El usuario inicia sesión con un nombre de usuario y una contraseña.
  2. El servidor verifica las credenciales y crea una "Sesión" en su base de datos (o memoria), generando un Session ID (ID de sesión) único.
  3. El servidor envía este Session ID de vuelta al navegador del usuario, que lo almacena en una cookie.
  4. En cada solicitud posterior, el navegador envía la cookie. El servidor busca el Session ID en su base de datos, ve a quién pertenece y permite el acceso.

¿Por qué se rompió este sistema?

Este sistema funcionó perfectamente durante 15 años. Pero luego, la arquitectura web moderna cambió. Las aplicaciones pasaron de servidores monolíticos a microservicios (microservices).

Imagina un sitio de comercio electrónico donde el "Servidor de Usuarios" maneja los inicios de sesión, el "Servidor de Productos" maneja el catálogo y el "Servidor de Pagos" maneja el cobro. Si el Servidor de Usuarios crea una sesión en su base de datos local, el Servidor de Productos no tiene idea de quién es el usuario porque no puede ver la base de datos del Servidor de Usuarios. Compartir estados de sesión en docenas de servidores distribuidos es increíblemente lento, costoso y difícil de escalar.

La Solución: Autenticación sin Estado (Stateless) con JWT

Los JSON Web Tokens (JWT) proporcionan una solución sin estado.

En lugar de almacenar una sesión en una base de datos y enviar al usuario un ID sin sentido, el servidor empaqueta toda la información necesaria del usuario (como su ID de Usuario y su rol) en un pequeño objeto JSON. Luego, el servidor firma digitalmente este objeto JSON usando una clave criptográfica secreta y envía todo el objeto firmado de vuelta al usuario. Esto es el JWT.

Cuando el usuario realiza su siguiente solicitud, envía el JWT junto con ella. El servidor receptor mira el token, verifica la firma digital para asegurarse de que no haya sido manipulado, y sabe inmediatamente quién es el usuario, ¡sin tener que buscar en una base de datos jamás!

Debido a que el token en sí mismo contiene los datos, y la firma garantiza su autenticidad, cualquier microservicio que conozca la clave secreta del servidor puede verificar el token al instante.

La Estructura de un JWT

Si observas un JWT en crudo, parece una cadena larga de texto aleatorio separada por dos puntos: xxxxxxx.yyyyyyy.zzzzzzz

Estas tres secciones son en realidad cadenas codificadas en Base64 que representan las tres partes del token: el Encabezado (Header), la Carga Útil (Payload) y la Firma (Signature).

1. El Encabezado (Header) - xxxxxxx

El encabezado típicamente consta de dos partes: el tipo de token (que es "JWT") y el algoritmo de firma que se está utilizando, como HMAC SHA256 (HS256) o RSA.

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

Este JSON está codificado en Base64Url para formar la primera parte del token.

2. La Carga Útil (Payload) - yyyyyyy

La carga útil contiene los claims (reclamaciones). Las reclamaciones son declaraciones sobre una entidad (típicamente, el usuario) y datos adicionales. Existen tres tipos de reclamaciones:

  • Reclamaciones registradas (Registered claims): Reclamaciones predefinidas recomendadas por el estándar JWT. Los ejemplos incluyen iss (emisor/issuer), exp (tiempo de expiración), sub (sujeto/ID de usuario) y aud (audiencia).
  • Reclamaciones públicas (Public claims): Reclamaciones personalizadas creadas por ti, pero deben definirse en un registro público para evitar colisiones.
  • Reclamaciones privadas (Private claims): Reclamaciones personalizadas creadas para compartir información específicamente entre tu servidor y el cliente. Por ejemplo, "role": "admin".
{
  "sub": "1234567890",
  "name": "John Doe",
  "role": "admin",
  "iat": 1516239022,
  "exp": 1516242622
}

Este JSON está codificado en Base64Url para formar la segunda parte del token.

ADVERTENCIA CRÍTICA: El encabezado y la carga útil solo están codificados (Base64), NO encriptados (cifrados). Cualquiera que intercepte un JWT puede decodificarlo fácilmente y leer la carga útil. Nunca pongas contraseñas, números de seguro social o datos financieros sensibles dentro de la carga útil de un JWT.

3. La Firma (Signature) - zzzzzzz

La firma es la parte más importante del JWT. Es lo que evita que los usuarios modifiquen sus propios tokens.

Para crear la firma, el servidor toma el encabezado codificado, la carga útil codificada y una Clave Secreta (Secret Key) altamente segura conocida solo por el servidor. Pasa estas tres piezas a través del algoritmo especificado en el encabezado (como HMAC SHA256).

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret_key
)

Si un usuario malintencionado intercepta su JWT, decodifica la carga útil, cambia "role": "user" a "role": "admin", y lo vuelve a codificar, el servidor lo rechazará. ¿Por qué? Porque el hacker no conoce la secret_key del servidor. Cuando el servidor reciba el token modificado, volverá a calcular la firma. La nueva firma no coincidirá con la antigua, y el servidor sabrá instantáneamente que el token fue falsificado (que fue manipulado).

Mejores Prácticas de JWT y Errores de Seguridad

Si bien los JWTs resuelven el problema de escalabilidad de las sesiones, introducen desafíos de seguridad completamente nuevos. Si estás implementando JWTs, debes seguir estas reglas:

1. Mantén la Vida Útil Corta (Expiración)

Dado que los JWT son sin estado, no hay una manera fácil de "revocar" o "destruir" un JWT desde el lado del servidor. Una vez que un servidor emite un JWT, es válido hasta que caduca. Si un hacker roba el token de un usuario, tiene acceso completo a esa cuenta.

Por lo tanto, tus JWTs deben tener una reclamación exp (expiración) muy corta, típicamente de 15 minutos. Para mantener al usuario conectado sin obligarlo a volver a ingresar su contraseña cada 15 minutos, se usa un Token de Actualización (Refresh Token) (un token separado de larga duración que se almacena de forma segura y que puede solicitar nuevos JWTs de corta duración).

2. Almacena los Tokens de Forma Segura

¿Dónde pones el JWT en el navegador?

  • Local Storage / Session Storage: Este es el lugar más común, pero también el más peligroso. Cualquier Javascript que se ejecute en tu página (incluidos los scripts maliciosos de ataques XSS) puede leer el almacenamiento local y robar el token.
  • Cookies HttpOnly: Este es el enfoque recomendado. Si envías el JWT dentro de una cookie HttpOnly y Secure, el navegador la envía automáticamente con cada solicitud, pero Javascript está completamente bloqueado para leer la cookie, lo que frustra los ataques XSS.

3. Valida el Algoritmo de Firma

Históricamente, algunas bibliotecas de JWT tenían una falla crítica donde un hacker podía cambiar el encabezado a "alg": "none" (no se requiere firma). El servidor lo aceptaría a ciegas. Asegúrate siempre de que tu framework backend tenga el algoritmo esperado codificado de forma rígida (por ejemplo, HS256) y rechace "none".

Conclusión

Los JSON Web Tokens (JWT) han cambiado fundamentalmente la forma en que las aplicaciones web modernas manejan la autenticación. Al empaquetar datos de identidad y autorización en un token verificado criptográficamente, eliminan la necesidad de bases de datos de sesión centralizadas, lo que permite que los microservicios se escalen de forma infinita e independiente.

Sin embargo, un gran poder conlleva una gran responsabilidad. Debido a que los JWT son sin estado y autónomos, el mal manejo de su almacenamiento, el hacer que duren demasiado o el poner datos confidenciales en la carga útil puede provocar brechas de seguridad catastróficas. Comprende la estructura, protege tus claves secretas, usa cookies HttpOnly, y los JWT servirán como una capa de seguridad robusta y sumamente rápida para tus aplicaciones.

Buy me a coffee