y enviárselo a su propio servidor, robando la identidad del usuario por completo.
Ventaja: Es sumamente fácil de leer y adjuntar a peticiones asíncronas vía código.
Opción B: Cookies Seguras (HttpOnly, Secure, SameSite=Lax) - Recomendado
- Vectores de ataque: Al activar
HttpOnly, JavaScript de cliente pierde el acceso al token, bloqueando los robos vía XSS. Sin embargo, al viajar automáticamente en las peticiones, introduce el riesgo de CSRF (Cross-Site Request Forgery).
- Mitigación: El uso de la bandera
SameSite=Lax junto con tokens anti-CSRF mitiga eficazmente este vector. Es la opción recomendada para almacenar tokens en entornos web de producción.
Arquitectura de Producción: Access Tokens y Refresh Tokens
Mantener un JWT activo por semanas es un riesgo de seguridad enorme: si el token es robado, el atacante tendrá acceso ilimitado. Para mitigar esto, las aplicaciones de producción implementan un esquema de doble token:
Comparativa de arquitectura entre Access Tokens y Refresh Tokens
- Access Token:
- Función: Autenticar las peticiones a la API.
- Duración: Muy corta (ej. 15 minutos).
- Almacenamiento: Idealmente en memoria JS (no se escribe en disco) o en cookies seguras de vida corta.
- Refresh Token:
- Función: Solicitar nuevos Access Tokens cuando expiren.
- Duración: Larga (ej. 7 a 30 días).
- Almacenamiento: Guardado obligatoriamente en una cookie
HttpOnly, Secure y SameSite=Lax en una ruta específica /api/refresh.
- Validación: Sí requiere una consulta a la base de datos (o Redis) en el servidor para verificar que el Refresh Token no haya sido revocado.
Para no morir en el intento y consejos que no pediste
Implementar JWT de manera stateless tiene consecuencias en la flexibilidad que debes conocer y gestionar desde el primer día de desarrollo.
El reto de la revocación (Listas negras en Redis)
La naturaleza stateless de JWT tiene un costo: no se puede invalidar un token de forma remota antes de su fecha de vencimiento. Si un usuario cambia su contraseña, cierra sesión o es bloqueado, su Access Token seguirá siendo válido en cualquier servidor hasta que expire.
Para solucionar esto sin perder todas las ventajas de rendimiento, se utiliza el patrón de lista negra (Blacklisting):
- Cuando un usuario cierra sesión, el servidor toma el
jti (identificador único del JWT) o su firma y lo almacena temporalmente en Redis con un tiempo de expiración idéntico al tiempo de vida restante del token.
- Durante la validación de peticiones, el servidor verifica rápidamente en Redis si el token está en la lista negra. Si está, bloquea el acceso.
- Una vez que pasa la hora de expiración natural del token, este se elimina automáticamente de Redis, manteniendo el tamaño del almacenamiento de la lista negra optimizado.
Checklist de Producción para JWT
- [ ] Claves de Firma Fuertes: Utiliza algoritmos robustos (ej. RS256 usando claves públicas/privadas en lugar de HS256) y rota las claves periódicamente.
- [ ] No almacenar datos sensibles: Asegúrate de que el payload no contenga información confidencial, ya que cualquiera puede decodificarlo.
- [ ] Validación de Claims Obligatoria: Valida siempre
exp (expiración), iat (emisión), y de ser posible iss (emisor) y aud (audiencia).
Reflexión Final
JWT es una herramienta potente para escalar APIs de microservicios y comunicar sistemas distribuidos sin sobrecargar las bases de datos de sesión. Sin embargo, su implementación en producción requiere extremo cuidado en la duración del token y la protección frente a ataques en el almacenamiento del cliente.
Conclusiones Clave:
- Nunca guardes datos sensibles en el payload: Base64 es legible para cualquiera.
- Mantén los Access Tokens con vida corta: 15 minutos es el estándar de seguridad óptimo.
- Protege tus Refresh Tokens: Guárdalos bajo cookies seguras
HttpOnly e implementa listas de revocación.