En este artículo vamos a analizar las ventajas y desventajas de usar un sistema de autenticación basado en JWT (JSON Web Tokens) frente al esquema tradicional basado en el uso de cookies y sesiones.
A fin de facilitar la comprensión, voy a presentarte una serie de resúmenes, que he ido adaptando a partir de recursos interesantes que encontré por la Internet. Si deseas consultar las fuentes originales, puedes encontrar los enlaces al final del artículo.
Sin más, empecemos.
Introducción
Para comprender mejor este artículo, es necesario que conozcas previamente qué son las cookies y su relación con las server-side sessions.
Si tienes en claro la diferencia entre cookies y sesiones, y cómo operan en conjunto, entonces podemos continuar hacia la primera pregunta.
Autenticación basada en tokens VS autenticación basada en cookies y sesiones
A continuación vamos a repasar cómo funcionan las cookies (en conjunto con sesiones) y los tokens, para que luego nos resulte más fácil resaltar las diferencias.
Autenticación basada en cookies
La autenticación basada en cookies ha sido el método predeterminado (y comprobado) para manejar la autenticación de usuarios durante mucho tiempo.
La autenticación basada en cookies presenta un estado (es stateful
).
Al iniciar sesión, luego que un usuario envía sus credenciales (y estas se validan), el servidor registra datos (con el fin de recordar que el usuario se ha identificado correctamente). Estos datos que se registran en el backend, en correspondencia con el identificador de sesión, es lo que se conoce como estado.
En el lado del cliente una cookie es creada para almacenar el identificador de sesión, mientras que los datos se almacenan en el servidor (y son llamados variables de sesión).
El flujo que sigue este sistema de autenticación tradicional es el siguiente:
- Un usuario ingresa sus credenciales (datos que le permiten iniciar sesión)
- El servidor verifica que las credenciales sean correctas, y crea una sesión (esto puede corresponderse con la creación de un archivo, un registro nuevo en una base de datos, o alguna otra solución server-side)
- Una cookie con el
session ID
es puesta en el navegador web del usuario - En las peticiones siguientes, el
session ID
es comparado con las sesiones creadas por el servidor - Una vez que el usuario se desconecta, la sesión es destruida en ambos lados (tanto en el cliente como en el servidor)
Autenticación basada en tokens
La autenticación basada en tokens ha ganado prevalencia en los últimos años debido al aumento de las Single Page Applications
, web APIs y la Internet de las cosas (Internet of Things
en inglés).
Cuando hablamos de autenticación con tokens, generalmente hablamos de autenticación con JSON Web Tokens (JWT).
Si bien existen diferentes implementaciones, los JWT se han convertido en el estándar de facto. Con ello en mente, en el resto del artículo, tokens y JWT se usarán indistintamente.
La autenticación basada en tokens carece de estado (es stateless
).
El servidor ya no guarda información de qué usuarios están conectados o qué tokens se han emitido. Esto es así porque cada solicitud realizada al servidor va acompañada de un token, y el servidor verifica la autenticidad de la solicitud basándose únicamente en el token.
Como ya comentamos antes, JWT define un formato para los tokens. Pero JWT no nos ata a ningún mecanismo de persistencia de datosen el lado del cliente y tampoco a ninguna regla de cómo se debe transportar el token.
Los tokens se envían generalmente como un Authorization header
, con el valor Bearer {JWT}
; pero pueden enviarse también en el cuerpo de una petición POST o incluso como un query parameter
.
Veamos cómo funciona:
- Un usuario ingresa sus credenciales (datos que le permiten iniciar sesión)
- El servidor verifica que las credenciales sean correctas, y devuelve un token firmado
- El token es guardado en el lado del cliente, comúnmente en el
local storage
(pero puede guardarse también en elsession storage
o incluso como una cookie) - Las peticiones siguientes al servidor incluyen este token (a través de un
Authorization header
o alguno de los otros métodos antes mencionados) - El servidor decodifica el JWT y si el token es válido procesa la solicitud
- Una vez que el usuario se desconecta, el token es destruido en el lado del cliente (no es necesaria la interacción con el servidor)
Ventajas de la autenticación basada en tokens
Luego de comprender cómo funcionanambos enfoques, vamos a ver las ventajas que presenta la autenticación basada en tokens sobre el enfoque tradicional basado en cookies.
Sin estado, escalable y desacoplado
Probablemente la mayor ventaja de usar tokens y no cookies es el hecho de que ofrecen una autenticación sin estado (stateless).
Desde backend no se necesita tener un registro de los tokens. Cada token es autónomo: contienen en sí mismos toda la data necesaria para confirmar su validez (así como también información puntual del usuario que ha iniciado sesión).
De esta forma, el único trabajo del servidor es: firmar tokens ante un inicio de sesión exitoso, y verificar que los tokens entrantes sean válidos.
Cross Domain y CORS
Las cookies funcionan bien con un dominio (o subdominio) en específico, pero cuando se trata de administrar cookies en diferentes dominios, el manejo se torna complicado.
En contraste, un enfoque basado en tokens con CORS habilitado hace que sea trivial exponer las APIs a diferentes servicios y dominios.
Dado que se requiere y se verifica un token en cada una de las llamadas al backend, siempre que haya un token válido, las solicitudes se pueden procesar. Sobre esto, hay algunos detalles que debemos tener en cuenta, y los abordaremos en la sección de Preguntas comunes).
Guardar datos en los JWT
Con un enfoque basado en cookies, simplemente guardamos el identificador de sesión.
Los tokens por otro lado nos permiten guardar cualquier tipo de metadata, siempre que se trate de un JSON válido.
La especificación de JWT indica que podemos incluir diferentes tipos de datos (llamados claims
), y que se pueden guardar como datos reservados, públicos y privados.
Dependiendo del contexto, podemos optar por usar una cantidad mínima de claims, y guardar sólo la identificación de usuario y el vencimiento del token, o bien podemos incluir claims adicionales, como el email del usuario, quién emitió el token, los alcances y/o permisos de los que dispone el usuario, etcétera.
Performance
Al utilizar una autenticación basada en cookies, desde backend se debe realizar una búsqueda de la sesión (correspondiente al identificador enviado por el cliente; ya sea en archivos, en una base de datos SQL tradicional o una alternativa NoSQL). En ese caso es muy probable que la ida y vuelta tome más tiempo si lo comparamos con la decodificación de un token. Además, como se pueden almacenar datos adicionales en los tokens (como el nivel de permisos), podemos disminuir la cantidad de búsquedas requeridas para obtener y procesar los datos solicitados.
Por ejemplo, supongamos que tenemos un recurso /api/orders
en nuestra API que devuelve las últimas órdenes registradas en nuestra aplicación, pero sólo los usuarios con rol administrador tienen acceso para ver esta data.
En un enfoque basado en cookies, una vez que se realiza la petición, desde backend es necesario hacer una consulta para verificar que la sesión es válida, otra búsqueda para acceder a los datos del usuario y verificar que tenga el rol de administrador, y finalmente una tercera consulta para obtener los datos.
Por otro lado, usando JWT, podemos guardar el rol del usuario en el token. Así, una vez que la petición se realiza y el token se valida, necesitamos realizar una sola consulta a la base de datos (para acceder a la información de las órdenes).
Te esperamos en la segunda parte del artículo en donde hablaremos mas acerca de estos temas, los cuales hoy en día son de vital importancia en el mundo de la tecnología.