Cuando inicias sesión en una aplicación moderna de una sola página (como React o Vue) o en una aplicación móvil, el servidor necesita una forma de recordar quién eres. Tradicionalmente, lo hacía almacenando un "ID de sesión" en una base de datos masiva en el servidor y colocando una cookie en su navegador. Cada vez que hacía clic en un botón, el servidor tenía que buscar esa identificación en su base de datos. Esto se llama autenticación con estado.
Sin embargo, en la era de los microservicios y el escalamiento de la nube, las bases de datos se convirtieron en un cuello de botella. Para resolver esto, los desarrolladores adoptaron la autenticación sin estado mediante tokens web JSON (JWT). Con JWT, el servidor no necesita recordar quién es usted: su navegador le dice al servidor exactamente quién es usted y utiliza criptografía para demostrarlo.
La anatomía de un JWT
Si inspecciona el tráfico de la red después de iniciar sesión en una aplicación moderna, probablemente verá un encabezado "Autorización: Portador" seguido de una larga cadena de caracteres de apariencia aleatoria separados por dos puntos. Eso es un JWT.
Un JWT consta exactamente de tres partes: Header.Payload.Signature.
1. El encabezado
La primera parte es un objeto JSON codificado en Base64URL que simplemente describe el token. Por lo general, contiene dos propiedades: el tipo de token (JWT) y el algoritmo de firma que se utiliza (como HMAC SHA256 o RSA).
2. La carga útil (reclamaciones)
La parte central también es un objeto JSON codificado en Base64URL. Aquí es donde viven los datos reales. Estos datos se denominan "reclamaciones". Por ejemplo, podría contener su ID de usuario, su función (por ejemplo, "Administrador") y una marca de tiempo de vencimiento. Debido a que esta carga útil se adjunta a cada solicitud, el servidor sabe instantáneamente quién es usted sin consultar una base de datos.
ADVERTENCIA CRÍTICA: La carga útil está simplemente codificada, no cifrada. Cualquiera que intercepte un JWT puede decodificarlo fácilmente y leer la carga útil. Nunca almacene contraseñas, números de seguridad social o datos confidenciales dentro de una carga útil de JWT.
3. La firma
Si alguien puede leer y editar la carga útil, ¿qué impide que un usuario malintencionado cambie su función de "Usuario" a "Administrador"? La respuesta es la Firma.
Para crear la firma, el servidor toma el encabezado, la carga útil y una clave secreta altamente segura (conocida solo por el servidor) y los ejecuta a través de un algoritmo criptográfico (como SHA256). El hash resultante se convierte en la Firma.
Cuando el servidor recibe un token del cliente, vuelve a calcular la firma utilizando su clave secreta. Si el usuario manipuló la carga útil (incluso cambiando una sola letra), la firma recalculada no coincidirá con la firma del token y el servidor rechazará instantáneamente la solicitud por considerarla fraudulenta.
Inspeccionar tokens de forma segura
¿Necesita leer la carga útil de un JWT para depurar su aplicación? Utilice nuestro decodificador JWT fuera de línea para inspeccionar los reclamos al instante sin enviar su token confidencial a un servidor remoto.
Abrir decodificador JWTPor qué los microservicios aman las JWT
Imagine una empresa como Netflix. Tienen un servidor de Autenticación, un servidor de Video Streaming y un servidor de Facturación. Si usaran sesiones tradicionales, cada servidor tendría que comunicarse constantemente con una base de datos central para verificar si un usuario ha iniciado sesión.
Con los JWT, el servidor de autenticación firma el token utilizando una clave privada. Luego, el usuario pasa ese token directamente al servidor de vídeo. Dado que el servidor de vídeo tiene la clave pública, puede verificar la firma de forma independiente. El servidor de vídeo sabe exactamente quién es el usuario sin siquiera hablar con el servidor de autenticación o una base de datos. Esto permite que la infraestructura crezca infinitamente sin cuellos de botella.
El lado oscuro: invalidación de tokens
Los JWT no son perfectos. Su mayor fortaleza (ser apátrida) es también su mayor debilidad. Debido a que el servidor no mantiene un registro de los tokens activos, no es fácil cerrar la sesión de un usuario ni invalidar un token específico antes de que caduque.
Si un pirata informático roba el JWT de un usuario, tendrá acceso completo hasta que se acabe la marca de tiempo de vencimiento del token. Para mitigar este riesgo, los ingenieros de seguridad utilizan un sistema de dos tokens:
- Tokens de acceso: JWT de corta duración (por ejemplo, 15 minutos) utilizados para solicitudes de API.
- Tokens de actualización: tokens con estado de larga duración almacenados de forma segura, utilizados estrictamente para solicitar nuevos tokens de acceso. Si una cuenta se ve comprometida, el servidor revoca el token de actualización y el token de acceso del hacker morirá naturalmente en 15 minutos.
Preguntas frecuentes (FAQ)
¿Dónde debo almacenar un JWT en la interfaz?
Almacenar JWT en localStorage los hace vulnerables a ataques de Cross-Site Scripting (XSS). El lugar más seguro para almacenar un JWT en un navegador web es dentro de una cookie HttpOnly, que impide que JavaScript acceda a él.
¿Qué sucede si se filtra la clave secreta de mi servidor?
Catástrofe. Si un pirata informático obtiene su clave secreta HMAC o su clave privada RSA, puede generar JWT válidos con cualquier carga útil que desee. Podrían crear tokens que se otorguen privilegios de "superadministrador" y su servidor los aceptará como válidos. Debes rotar tus llaves inmediatamente.
¿Son los JWT más rápidos que las cookies de sesión?
No necesariamente. Los JWT tienen un tamaño de archivo significativamente mayor que un ID de sesión de 32 caracteres, lo que significa que consumen más ancho de banda de la red en cada solicitud. Su ventaja en velocidad proviene completamente de evitar las búsquedas de bases de datos en el backend.