En una frase
Un JSON Web Token (JWT) es una forma compacta y segura para URLs de representar declaraciones (claims) que se transfieren entre dos partes. Se usa típicamente para autenticación y autorización de una manera que puede ser verificada y es de confianza.
El problema que resuelve
En los viejos tiempos —digamos, a principios de los 2000— si iniciabas sesión en un sitio web, el servidor creaba una "sesión" para ti. Era como un archivito en el servidor que decía: "El usuario 123 ha iniciado sesión y ha puesto un pollo de hule en su carrito de compras". El servidor le daba a tu navegador una pequeña cookie con un ID de sesión, como el ticket del guardarropa. En cada solicitud siguiente, tu navegador presentaba el ticket, el servidor lo buscaba, encontraba tu archivo y recordaba quién eras.
Esto funcionaba bien para un único servidor monolítico. Pero luego la web explotó. Aparecieron los microservicios, las aplicaciones de página única (SPAs) y las apps móviles, todos hablando con el mismo backend. Ahora, tu solicitud de inicio de sesión podría ir al Servidor A, pero tu siguiente solicitud para obtener tu perfil podría ir al Servidor B. ¿Cómo sabe el Servidor B sobre el archivo de sesión en el Servidor A?
Podrías forzar a un usuario a hablar siempre con el mismo servidor ("sesiones pegajosas" o sticky sessions), pero eso es un cuello de botella. Podrías crear una base de datos de sesiones centralizada (como Redis) que todos los servidores compartan, pero esa es otra pieza de infraestructura que gestionar y otro punto de fallo.
El problema principal es el estado (statefulness). El servidor tiene que recordarte.
Los JWTs (pronunciado "yots") le dieron un giro de 180 grados a esta idea. ¿Y si el usuario pudiera llevar su propia prueba de identidad, como un pasaporte? El propio token contendría toda la información que el servidor necesita: quién es el usuario, qué tiene permitido hacer y cuándo expira su acceso. El servidor no tiene que recordar nada entre solicitudes. Esto es autenticación sin estado (stateless), y es la clave para construir sistemas distribuidos y escalables. El servidor solo necesita verificar si el pasaporte (el JWT) es válido y no ha sido falsificado.
Cómo funciona por dentro
Un JWT no es una masa indescifrable de galimatías. Es una cadena de texto muy específica y estructurada, compuesta por tres partes separadas por puntos (.).
xxxxx.yyyyy.zzzzz
Desglosemos cada parte.
El Header (La etiqueta de "Tipo")
La primera parte es el header (cabecera). Es un simple objeto JSON que contiene metadatos sobre el propio token, principalmente el algoritmo de firma utilizado y el tipo de token.
{
"alg": "HS256",
"typ": "JWT"
}
alg: El algoritmo de firma.HS256significa que este token está firmado con HMAC-SHA256, un algoritmo simétrico (más sobre esto en un momento). Otras opciones comunes incluyenRS256(usando un par de claves pública/privada RSA).typ: El tipo de token. Para los JWTs, esto es simplemente "JWT".
Este JSON se codifica en Base64Url para producir la primera parte del token. Base64 es un esquema de codificación, no de cifrado. Simplemente convierte datos binarios en una cadena de texto que es segura para transmitir por la web. Piensa en ello como escribir "ESTO ES UNA POSTAL" en el reverso de una postal: cualquiera que la intercepte puede leerla.
El Payload (El departamento de "Declaraciones")
La segunda parte es el payload (carga útil). Esta es la parte jugosa. Es otro objeto JSON que contiene las "declaraciones" (claims), que son afirmaciones sobre el usuario (el "sujeto") y otros datos útiles.
{
"sub": "10987-23456-98765",
"name": "Grace Hopper",
"admin": true,
"iat": 1516239022,
"exp": 1516242622
}
Las declaraciones vienen en tres sabores:
- Declaraciones Registradas: Son un conjunto de declaraciones predefinidas y recomendadas para proporcionar interoperabilidad. No son obligatorias, pero son súper útiles.
| Claim | Nombre | Descripción |
|---|---|---|
iss |
Emisor (Issuer) | Quién emitió el token (ej. https://api.misitiogenial.com). |
sub |
Sujeto (Subject) | El usuario o entidad sobre la que trata el token (ej. un ID de usuario). |
aud |
Audiencia (Audience) | Para quién está destinado el token (ej. https://api.misitiogenial.com). |
exp |
Tiempo de Expiración | Cuándo expira el token. Un timestamp de Unix numérico (segundos desde la época). |
iat |
Emitido En (Issued At) | Cuándo se emitió el token. También un timestamp de Unix. |
- Declaraciones Públicas: Son declaraciones personalizadas que tú creas, pero para evitar colisiones de nombres, deben definirse en el registro de IANA JSON Web Token Claims o ser una URI que contenga un espacio de nombres resistente a colisiones.
- Declaraciones Privadas: Son las declaraciones personalizadas más comunes, creadas para compartir información entre partes que acuerdan usarlas (como
admin: trueen nuestro ejemplo). Aquí es donde pones los datos específicos de tu aplicación.
Al igual que el header, todo el JSON del payload se codifica en Base64Url para formar la segunda parte del JWT. De nuevo, esto no está cifrado. Nunca pongas información sensible como contraseñas en el payload.
La Firma (El Sello Anti-Manipulación)
Esta es la parte que proporciona la seguridad. La firma se utiliza para verificar que el remitente del JWT es quien dice ser y para asegurar que el mensaje no fue alterado en el camino.
Se crea tomando el header codificado, el payload codificado, una clave secreta y pasándolos por el algoritmo especificado en el header. Para nuestro ejemplo HS256, el proceso se ve así:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
tu-secreto-de-256-bits
)
La clave del asunto: se utiliza un secreto que solo el servidor conoce. Cuando el servidor recibe un JWT, vuelve a ejecutar este mismo cálculo con el header y el payload que recibió. Si la firma que genera coincide con la firma del token, el servidor sabe dos cosas:
- Autenticidad: El token fue creado por alguien que conoce la clave secreta (es decir, el propio servidor).
- Integridad: El header y el payload no han sido manipulados. Si un atacante cambiara
"admin": falsea"admin": true"en el payload, la firma ya no coincidiría.
Esta firma es el sello holográfico anti-manipulación de nuestro pasaporte.
Historias del mundo real
El Laberinto de los Microservicios
Una empresa de e-commerce de rápido crecimiento, "ScaleFast", decidió dividir su gigantesco backend monolítico en una flota de microservicios: uno para usuarios, uno para pedidos, uno para inventario, etc. El sistema antiguo usaba una sesión del lado del servidor. Pero en el nuevo mundo, ¿cómo sabe el OrderService que una solicitud realmente vino de un usuario autenticado, sin tener que llamar al UserService en cada una de las solicitudes? Eso sería lento y anularía el propósito del desacoplamiento.
La solución fue JWT. Cuando un usuario inicia sesión, el nuevo AuthService emite un JWT que contiene el userId y sus roles. El navegador del usuario incluye este JWT en el header Authorization de cada solicitud a otros microservicios. El OrderService y el InventoryService no necesitan hablar con el AuthService; solo necesitan conocer la clave secreta compartida. Pueden verificar de forma independiente la firma del JWT, confiar en el userId que contiene y procesar la solicitud.
Lección: Los JWTs son la lingua franca de la autenticación en microservicios, permitiendo que los servicios no tengan estado y sean verificables de forma independiente.
La Saga de la Single-Page App
Un desarrollador llamado Alex estaba construyendo un elegante dashboard con React. El frontend era una Aplicación de Página Única (SPA) servida desde un host estático, y hablaba con una API de backend separada. Alex estaba lidiando con la autenticación tradicional basada en cookies, enfrentándose a una pesadilla de problemas de Cross-Origin Resource Sharing (CORS) porque el frontend y el backend estaban en dominios diferentes.
El equipo se cambió a JWT. Ahora, después de que un usuario inicia sesión con su nombre de usuario y contraseña, la API le devuelve un JWT. La aplicación de React de Alex almacena este token en memoria y lo adjunta a cada llamada a la API: Authorization: Bearer <el-jwt>. El backend de la API es sin estado; solo verifica el token bearer en cada solicitud entrante. Se acabaron los dolores de cabeza con las cookies y CORS.
Lección: Los JWTs proporcionan una credencial limpia y portable que funciona de maravilla para desacoplar las aplicaciones de frontend modernas de las APIs de backend.
Errores y trampas comunes
- Poner datos sensibles en el payload. ¡Detente! El payload está codificado en Base64Url, que es trivialmente reversible. No está cifrado. Cualquiera que se haga con el token puede leer el payload. Trátalo como una postal, no como una carta sellada.
- Olvidar verificar la firma. ¿De qué sirven las medidas de seguridad de un pasaporte si el agente de la frontera no las revisa? Simplemente decodificar el payload y confiar en su contenido sin verificar la firma es una vulnerabilidad de seguridad catastrófica. Un atacante podría falsificar cualquier payload que quisiera.
- Confiar ciegamente en el header
alg. Una famosa vulnerabilidad del pasado consistía en que los atacantes creaban un token y cambiaban el header a{"alg": "none"}. Algunas bibliotecas mal configuradas veían "none" y "verificaban" la firma, bueno, no haciendo nada, aceptando el token falsificado como válido. Haz que tu servidor siempre imponga un algoritmo específico y esperado (por ejemplo,HS256). - Filtrar tu clave secreta simétrica. Para algoritmos HMAC como
HS256, la clave secreta son las llaves del reino. Si se filtra, cualquiera puede falsificar tokens para cualquier usuario con cualquier permiso. Guárdala como si fuera una contraseña. - No establecer una declaración de expiración (
exp). Un token que vive para siempre es un riesgo enorme. Si alguna vez se ve comprometido, un atacante puede usarlo indefinidamente. Siempre establece un tiempo de expiración razonablemente corto y usa un mecanismo de refresh token para sesiones más largas.
Por qué debe estar en tu radar
Deberías pensar en "JWT" siempre que estés lidiando con autenticación o autorización en un entorno distribuido.
- Estás construyendo una API para una Single-Page App (SPA) o un cliente móvil.
- Estás diseñando una arquitectura de microservicios donde los servicios necesitan confiar en las solicitudes de los demás.
- Necesitas una autenticación sin estado que pueda escalar horizontalmente sin un almacén de sesiones compartido.
- Estás implementando flujos de autorización de un solo uso, como enlaces para restablecer contraseñas o verificación de correo electrónico, donde un token autocontenido y con vencimiento es la solución perfecta.
Es el estándar moderno para representar declaraciones de forma segura, y entender sus fortalezas —y debilidades— es algo no negociable para el desarrollador de hoy en día.
Profundiza más
- RFC 7519: La especificación oficial para JSON Web Token (JWT). La fuente de la verdad.
- jwt.io: Un recurso fantástico con un depurador en vivo y una lista de bibliotecas para casi todos los lenguajes.
- OWASP JWT Cheat Sheet: Una guía esencial sobre las mejores prácticas de seguridad y los peligros del uso de JWTs (los consejos son independientes del lenguaje).
- MDN Web Docs: Authorization header: Aprende sobre el esquema de autenticación
Bearercomúnmente usado para transmitir JWTs. - Wikipedia: JSON Web Token: Una buena visión general de alto nivel del concepto y su historia.