Definición
¿Recuerdas esas pulseras que te dan en los parques de atracciones o festivales de música? Esas que tienen un patrón especial o un chip que seguridad puede escanear para verificar que pagaste la entrada, qué tipo de boleto tienes e incluso a qué áreas adicionales puedes acceder. Un JWT (pronunciado “yot”) funciona exactamente igual para las aplicaciones web: es un pase compacto y autónomo que lleva información sobre quién eres y qué puedes hacer.
JWT significa JSON Web Token, y es una de las formas más utilizadas para manejar la autenticación en internet hoy en día. Cuando inicias sesión en un sitio web, en lugar de que el servidor mantenga un registro de tu sesión en una base de datos (lo cual se complica cuando tienes millones de usuarios), te da un JWT: una cadena especial de caracteres que contiene tu información de identidad, firmada digitalmente para que nadie pueda manipularla. Cada vez que haces una petición a ese sitio web, envías este token, y el servidor puede verificar que es legítimo sin consultar nada.
Un JWT tiene tres partes separadas por puntos: un header (que describe cómo está protegido el token), un payload (que contiene la información real sobre ti, llamada “claims”) y una firma (que prueba que el token no ha sido modificado). Lo ingenioso es que cualquiera puede leer la información en un JWT (solo está codificada, no cifrada), pero solo alguien con la clave secreta puede crear una firma válida. Así que si alguien intenta cambiar el payload para darse privilegios de administrador, la firma no coincidirá y el servidor lo rechazará.
Ejemplo
Escenario Real 1: Single Sign-On (SSO) Cuando haces clic en “Iniciar sesión con Google” en un sitio como Canva, Google verifica tu identidad y le da a Canva un JWT. Este token contiene tu email, nombre y una declaración verificada de que “Google confirma que esta persona es quien dice ser”. Canva confía en la firma de Google, así que te deja entrar sin ver nunca tu contraseña de Google. El JWT viaja con cada petición que haces a Canva.
Escenario Real 2: Autenticación en App Móvil Cuando inicias sesión en Spotify en tu teléfono, recibes un JWT que tu app guarda localmente. Durante las siguientes horas, cada vez que reproduces una canción, creas una playlist o navegas por recomendaciones, tu app envía este JWT con cada petición. Los servidores de Spotify verifican el token instantáneamente sin consultar una base de datos central: así es como millones de personas pueden hacer streaming simultáneamente.
Escenario Real 3: Comunicación entre Microservicios En la arquitectura de Netflix, cuando el “servicio de recomendaciones” necesita obtener tu historial de visualización del “servicio de historial”, pasa tu JWT. El servicio de historial puede verificar que estás autorizado a ver estos datos comprobando la firma del token, sin llamar a un servidor de autenticación central. Esto hace que todo el sistema sea más rápido y escalable.
Escenario Real 4: Rate Limiting en APIs Cuando usas una API del clima como OpenWeatherMap, tu JWT puede contener claims sobre tu nivel de suscripción. La API comprueba estos claims para determinar si puedes hacer 60 peticiones por minuto (tier gratuito) o 3000 peticiones por minuto (tier profesional). Toda esta información viaja en el propio token, sin necesidad de consultar la base de datos.
Analogía
La Pulsera del Festival: Cuando entras a un concierto, te dan una pulsera. Puede ser de un color específico (VIP vs entrada general), tener un patrón holográfico (para evitar falsificaciones) y quizás un chip que codifica la información de tu entrada. Seguridad puede verificar rápidamente tu nivel de acceso mirando la pulsera sin consultar una lista de invitados. Los JWTs funcionan igual: llevan tu información de acceso, son a prueba de manipulación gracias a las firmas y pueden verificarse rápidamente.
El Documento Notariado: Imagina un documento que declara quién eres y qué estás autorizado a hacer, firmado por un notario público. Cualquiera puede leer el documento, pero el sello del notario prueba que es legítimo. Si alguien cambia el documento, el sello se invalida. Un JWT es como un documento notariado digital: legible por cualquiera, pero la firma prueba su autenticidad.
El Pase de Abordar: Tu pase de abordar del avión contiene tu nombre, número de vuelo, asiento y grupo de embarque. Seguridad del aeropuerto lo escanea para verificar que es legítimo (comprobando la firma del código de barras) sin llamar a la aerolínea. La información está ahí mismo en el pase, codificada en un formato que no se puede falsificar. Los JWTs son pases de abordar digitales para aplicaciones web.
El Gafete del Empleado: En una empresa grande, tu credencial puede tener tu foto, nombre, departamento y nivel de acceso impresos, además de un chip que los lectores de puertas pueden escanear. Diferentes puertas dan acceso basándose en leer tu credencial, sin necesidad de consultar un ordenador central para cada puerta. Los JWTs cumplen el mismo propósito en sistemas digitales.
Ejemplo de Código
// Crear JWT
const jwt = require('jsonwebtoken');
const payload = {
sub: 'user123', // Subject (ID de usuario)
name: 'John Doe',
role: 'admin',
iat: Math.floor(Date.now() / 1000), // Emitido en
exp: Math.floor(Date.now() / 1000) + (60 * 60) // Expira en 1 hora
};
const secret = process.env.JWT_SECRET;
const token = jwt.sign(payload, secret, { algorithm: 'HS256' });
// Verificar JWT
try {
const decoded = jwt.verify(token, secret, {
algorithms: ['HS256'],
maxAge: '1h'
});
console.log('Token válido:', decoded);
} catch (err) {
console.error('Token inválido:', err.message);
}
// Usar con API
fetch('https://api.example.com/data', {
headers: {
'Authorization': `Bearer ${token}`
}
});
Diagrama
flowchart TB
subgraph Estructura["Estructura JWT: header.payload.signature"]
direction LR
Header["eyJhbGci...
(Header)"]
Dot1["."]
Payload["eyJzdWIi...
(Payload)"]
Dot2["."]
Sig["SflKxwRJ...
(Firma)"]
Header --- Dot1 --- Payload --- Dot2 --- Sig
end
subgraph Decodificado["Contenido Decodificado"]
direction TB
H["Header (JSON)
{
alg: RS256,
typ: JWT
}"]
P["Payload (JSON)
{
sub: user123,
name: Juan,
exp: 1699999999,
iat: 1699996399
}"]
S["Firma
RSASHA256(
base64(header) +
base64(payload),
secreto
)"]
end
Header --> H
Payload --> P
Sig --> S
subgraph Validacion["Flujo de Validación"]
V1["1. Decodificar header y payload"]
V2["2. Verificar firma con secreto/clave pública"]
V3["3. Comprobar claims exp, iat, nbf"]
V4["4. Verificar iss y aud"]
V1 --> V2 --> V3 --> V4
end
Notas de Seguridad
CRÍTICO - …
Configuración y Validación:
- Usa algoritmos fuertes (RS256 para asimétrico, HS256 para simétrico; evita el algoritmo “none”).
- Valida la firma en cada petición usando bibliotecas apropiadas.
- Comprueba los claims exp (expiración), nbf (no antes de), iat (emitido en).
- Verifica los claims iss (emisor) y aud (audiencia).
- Mantén los tokens de corta duración (5-60 minutos).
- Almacena los secretos/claves privadas de forma segura.
Monitoreo y Protección:
- Transmite solo por HTTPS.
- Los JWTs no pueden revocarse antes de su expiración (usa expiración corta + refresh tokens o mantén una lista de denegación).
- NO almacenes datos sensibles en el payload (está codificado en base64, no cifrado).
- Implementa rotación de tokens.
- Valida que el header alg coincida con el algoritmo esperado.
- Usa el claim jti (JWT ID) para prevención de replay si es necesario.
- Considera JWE para claims sensibles.
Buenas Prácticas
- Usa algoritmos de firma fuertes (RS256 para asimétrico, HS256 con secreto fuerte)
- Establece tiempos de expiración cortos (5-60 minutos) y usa refresh tokens
- Almacena tokens de forma segura (cookies httpOnly para web, almacenamiento seguro para móvil)
- Implementa mecanismo de refresh token con rotación
- Nunca almacenes datos sensibles en el payload (solo está codificado en base64, no cifrado)
- Valida todos los claims en el servidor (exp, iss, aud, nbf)
Errores Comunes
Usar algoritmo “none” (vulnerabilidad de seguridad), almacenar JWTs en localStorage sin protección XSS, no validar la firma en el servidor, incluir datos sensibles en el payload, olvidar comprobar el claim exp, usar secretos de firma débiles, no implementar refresh de tokens, confiar en la validación de tokens del lado del cliente.