¿Qué son los JSON Web Tokens y por qué son revolucionarios en la autenticación?
La autenticación es un componente crucial en la seguridad web, y la llegada de los JSON Web Tokens (JWT) ha revolucionado cómo manejamos las sesiones y accesos entre el front-end y el back-end. A diferencia de las cookies tradicionales que dependen del almacenamiento de sesiones en el servidor, los JWT son stateless, lo que significa que no necesitas guardar información en memoria o bases de datos. Este enfoque no solo resuelve problemas comunes en sistemas distribuidos, sino que también permite una escalabilidad sin precedentes.
¿Cómo se manejaba la autenticación antes de los JWT?
Históricamente, la autenticación en web se gestionaba con sesiones que se almacenaban en el servidor. Aquí te dejamos un esquema sencillo de cómo se hacía:
Cliente (Front-end): Aplicaciones en Angular, React o cualquier otro cliente que se conecta a nuestro back-end.
Sesión: Se guardaba una sesión en cookies que se transmitían al back-end.
Back-end: Mantenía la sesión en memoria o en la base de datos, y comprobaba la autenticidad de la sesión.
Sin embargo, este método presenta problemas cuando necesitamos escalar, especialmente si requerimos distribuir nuestra API en múltiples servidores alrededor del mundo. La sesión se vinculaba a un servidor particular, lo que causaba problemas de disponibilidad y fallos en el manejo de sesiones.
¿Qué beneficios ofrecen los JSON Web Tokens?
Los JWT se destacan por ser una tecnología sin estado (stateless), permitiendo que toda la información necesaria para autenticar se incluya directamente en el token:
Escalabilidad y Distribución: Al no depender del almacenamiento en el servidor, los JWT permiten la creación de sistemas distribuidos con balanceo de carga en diferentes nodos y servidores.
Compatibilidad Multi-Plataforma: A diferencia de las cookies, que son eficaces solamente dentro de navegadores, los JWT son ideales para aplicaciones móviles y otros tipos de cliente.
Seguridad: Los tokens pueden ser firmados y verificados, asegurando que solo quienes tengan la clave secreta puedan validarlos.
Comprendiendo la estructura de un JSON Web Token
Un JWT tiene una estructura clara que facilita su uso en múltiples aplicaciones. Esta se compone de tres partes separadas por puntos:
Header: Contiene la información sobre el algoritmo de encriptación utilizado (como HS256) y el tipo de token.
Payload: Es el corazón del JWT, donde se almacena la información esencial como el sub (subject), que identifica al usuario, y otros atributos personalizados.
Signature: Es una firma que combina el header y el payload usando una clave secreta. Solo aquel con la clave podrá verificar la autenticidad del token.
¿Cómo se utiliza el header en un JWT?
El header de un JWT especifica tanto el algoritmo de encriptación como el tipo de token. Por lo común, estos parámetros no se modifican y garantizan que los receptores del token sepan cómo procesar la información que sigue.
{"alg":"HS256","typ":"JWT"}
¿Qué información se incluye en el payload?
La sección de payload puede incluir cualquier tipo de claims, como la identidad del usuario, roles, permisos y cualquier otra información relevante que necesites para autenticar y autorizar peticiones. Todo esto sucede sin comprometer la seguridad porque estos datos son parte de un token firmado.
La signature es vital para garantizar que el token no ha sido alterado. Este se genera en el back-end combinando el header y el payload con una clave secreta conocida solo por el back-end. Esto permite que el servidor verifique si el token ha sido manipulado.
La adopción de JSON Web Tokens transformó profundamente las estrategias de autenticación y seguridad en aplicaciones modernas. Gracias a su flexibilidad, compatibilidad y enfoque sin estado, los JWT representan una herramienta poderosa para desarrollar sistemas seguros y escalables en diversas plataformas.
Es un estándar abierto (RFC 7519) que define una forma compacta y autónoma de transmitir información de forma segura entre partes como un objeto JSON. Esta información se puede verificar y confiar porque está firmada digitalmente. Los JWT se pueden firmar usando una palabra secreta (con el algoritmo HMAC) o un par de claves públicas / privadas usando RSA o ECDSA.
¿Cuándo deberíamos utilizar JSON Web Tokens?
Autorización: este es el escenario más común para usar JWT. Una vez que el usuario haya iniciado sesión, cada solicitud posterior incluirá el JWT, lo que le permitirá acceder a rutas, servicios y recursos que están autorizados con ese token. El inicio de sesión único es una función que se utiliza ampliamente con JWT en la actualidad, debido a su pequeña sobrecarga y su capacidad para usarse fácilmente en diferentes dominios o servidores distribuidos.
Intercambio de información: los JWT son una buena forma de transmitir información de forma segura entre varias partes. Debido a que los JWT se pueden firmar, por ejemplo, utilizando pares de claves públicas / privadas, se puede estar seguro de que los remitentes son quienes dicen ser. Además, como la firma se calcula utilizando las cabeceras y el payload, también se puede verificar que el contenido no haya sido manipulado.
Me encanto !
JWT permite comprobar, esa comprobación nos da un token, una llave para poder acceder a la sesión.
Antes se tenía una sesión que se transmitía por medio de una cookie al backend, y el backend guardaba la sesión en memoria o a veces la guardaba en la BD.
Una cookie tiene información adentro, por medio de ella se generaba la sesión, se envía al backend y el backend la comprobaba. El problema de esto es cuando se quiere escalar hacia más clientes o al hacer una distribución de la API.
Por ejemplo, antes había problema cuando se deseaba hacer un sistema distribuido, un balanceo de cargas en diferentes maquinas, es decir, correr la API en diferentes nodos a través del mundo ya que la sesión se mantenía en la maquina donde se había establecido la conexión. Al conectarse a otra maquina, la sesión se perdía.
Un ventaja de JWT es que son stateless, es decir, no se guardan en memoria y en base de datos. Literal, es un token ya encriptado que contiene la información de cómo identificar al usuario y los permisos, por lo tanto ya no hay necesidad de guardar la sesión en la maquina y el token va a permitir hacer esas comprobaciones, y con ello es posible hacer distribución de los sistemas, hacer un sistema que esté clusterizado.
Las ventajas de JWT es que permite soportar diferentes clientes, que sea stateless y poder hacer un sistema distribuido.
Página oficial de JWT:
Un JWT tiene tres partes, cada parte va dividida por un punto:
Header → Dice el algoritmo de encriptación y el tipo (usualmente no se modifica).
Payload → Viene la información que vamos a encerrar en el token. Viene el sub (el sujeto, dueño del token, permite identificar al usuario), después la información que queremos añadir incluida la fecha en que se generó el token (iat).
Verify Signature → Una forma para verificar el token, combina el header y payload, y se firma con una palabra clave (llave secreta). Solo el que tenga esa llave puede verificar si el token es original, si es verificado. Solo el backend debe tener ella llave, él mismo genera y verifica con esa llave.
JSON Web Token (JWT) es un estándar abierto (RFC-7519 Fuente: aquí) basado en JSON para crear un token que sirva para enviar datos entre aplicaciones o servicios y garantizar que sean válidos y seguros.
JSON Web Token (JWT) es una tecnología moderna que nos permite comprobar, por medio de esa comprobación nos dan un token, es decir una llave con el cual vamos a poder acceder.
¿Cómo se accedía sin hacer la comprobación con JWT? 🚪
Cuando cualquier cliente proveniente del frontend que se quiera conectar al backend (por ejemplo en tecnología tipo browser que es el navegador), se hace por medio de una sesión que se transmite por una “cookie” al backend (recordar que una cookie contiene información) y el backend mantiene esa sesión en memoria o la guarda en la base de datos, se pasa la información a través de la sesión y se corrobora esa información con el cliente (en el browser).
Cuando es una sesión no genera tantos problemas cuando se escala el número de consultas al mismo tiempo:
Por ejemplo cuando se quiere hacer un balanceo de la API a diferentes máquinas o dispositivos, es decir distribuirlo o correr el backend de la API a diferentes nodos a través del mundo se presentan los problemas para mantener la sesión abierta, porque al tener la sesión abierta de una máquina y permitir el acceso de otra, se debe cerrar la primera máquina para permitir que una segunda se conecte.
Con JWT se evita esos problemas de sesión porque son stealers.
¿Qué significa de JWT sean stealers? 🚓
Significa que no tienen que guardar en memoria ni en base de datos para acceder, simplemente generan un token que ya viene encriptado y contiene la información de cómo se puede identificar el usuario y también los permisos, de este modo ya no es necesario hacer sesión en la máquina y por medio del token es que se hacen las comprobaciones, permitiendo la distribución del sistema.
Ventajas del JWT 🏆
Dado que la cookie solo se podía consultar en el navegador (en el browser), con los JWT se abren alternativas de tipo de consultas; el caso más común de uso de los JWT es para manejar la autenticación en aplicaciones móviles o web. Para esto cuando el usuario se quiere autenticar manda sus datos de inicio de sesión al servidor, este genera el JWT y se lo manda a la aplicación cliente, luego en cada petición el cliente envía este token que el servidor usa para verificar que el usuario este correctamente autenticado y saber quien es.
Este igual no es el único caso de uso para JWT, es posible usarlo para transferir cualquier dato entre servicios de nuestra aplicación y asegurarnos de que sea siempre válido. Por ejemplo si tenemos un servicio de envío de email otro servicio podría enviar una petición con un JWT junto al contenido del mail o cualquier otro dato necesario y que estemos seguros que esos datos no fueron alterados de ninguna forma. (Fuente: aquí).
¿Qué tiene un JWT? 📥
El JWT consta de tres (3) partes:
Cada parte está dividida de un punto, la primera parte se llama “Header” e indica en qué algoritmo de encriptación y cuál es el tipo (esto no se modifica):
En la segunda parte se encuentra el “Payload” que contiene la información que se va a encerrar en ese token y este a su vez contiene a:
“sub” que viene siendo el sujeto,
también el “name” que es el nombre del dueño del token que permite identificar al usuario y se puede añadir más información.
Y está el “iat” que indica la fecha que se generó el token:
En la tercera parte está “Verify Signature” que permite verificar el token, lo que hace es combinar el “Header” con el “Payload” y lo firma con una palabra clave que se puede asignar arbitrariamente cunado se genera el token, solo el que tenga esa clave o llave secreta puede verificar que ese token es verdadero o genuino, por lo tanto solo el backend debe tener esa llave (el usuario no ese token):
Hola developers! He invertido más de 10h intentando resolver este error que comparto a continuación:
{"message":"The server does not support SSL connections","stack":"SequelizeConnectionError: The server does not support SSL connections\n at Client._connectionCallback (C:\\Users\\tonib\\dev\\courses\\platform\\Platzi\\onlineStoreProject\\authPassportJsJWTPart\\node_modules\\sequelize\\lib\\dialects\\postgres\\connection-manager.js:146:20)\n at Client._handleErrorWhileConnecting (C:\\Users\\tonib\\dev\\courses\\platform\\Platzi\\onlineStoreProject\\authPassportJsJWTPart\\node_modules\\pg\\lib\\client.js:305:19)\n at Client._handleErrorEvent (C:\\Users\\tonib\\dev\\courses\\platform\\Platzi\\onlineStoreProject\\authPassportJsJWTPart\\node_modules\\pg\\lib\\client.js:315:19)\n at Connection.emit (node:events:390:28)\n at Socket.<anonymous> (C:\\Users\\tonib\\dev\\courses\\platform\\Platzi\\onlineStoreProject\\authPassportJsJWTPart\\node_modules\\pg\\lib\\connection.js:71:23)\n at Object.onceWrapper (node:events:510:26)\n at Socket.emit (node:events:390:28)\n at addChunk (node:internal/streams/readable:324:12)\n at readableAddChunk (node:internal/streams/readable:297:9)\n at Socket.Readable.push (node:internal/streams/readable:234:10)"}
¿Alguien sabe como puedo solucionarlo para poder continuar con las clases?
La verdad es que es bastante frustrante porque no sé de donde viene y me está impidiendo hacer cualquier petición, gracias de antemano!
¡Hola! :D
¿Cuál es el problema que tienes?, ¿en qué te puedo ayudar? Compártenos tu código por favor. Puedes adjuntar imágenes arrastrándolas a esta ventana de comentario.
Nunca pares de aprender 💚
Hola, el usuario es capaz de ver el JWT?
No, el JWT funcionaría en ese caso como el hash, el usuario no tiene que ver esa información.
Si los tokens no se guardan en memoria y en base de datos entonces dónde se guardan?
Tengo la misma duda
Se almacena en localStorage o sessionStorage, que son APIs proporcionadas por el navegador
¿Qué es un JWT? 🔰
JWT (JSON Web Tokens) es una tecnología moderna que nos permite comprobar datos y en el caso de ser cierto nos dará una llave. Es una forma de manejar sesiones.
Antes, el frontend mandaba una sesión a través de una cookie al backend y éste lo mantenía en memoria o en base de datos. Ésto trae problemas a la hora de escalar la app, porque si, por ejemplo, queriamos usar distintos servidores, la sesión se perdía cuando tocaba cambiar de servidor.
Otra desventaja, es que esas cookies funcionaban sólo en navegadores. Si queríamos pasar a mobile, había que usar otras técnicas.
Los JWT son stateless. Es decir que no importa dónde éste, dentro suyo tiene información que dice si inició sesión y qué permisos tiene.
Composición de un JWT
Tiene tres partes. Son separadas por un punto.
Header: Nos da el algoritmo de encriptación y el tipo
Payload: Información encerrada. Dueño del token, fecha de creación, etc.
Verify Signature: Key que verifica que existe el user. La key es sólo del backend.
Si quieres saber más de JWT, recomiendo ir a la documentación oficial
Un JSON Web Token (JWT) se compone de tres partes, cada una separada por un punto:
Header: Contiene información sobre el tipo de token (JWT) y el algoritmo de firma utilizado (por ejemplo, HMAC SHA256).
Payload: Almacena las afirmaciones (claims) sobre el usuario y otros datos. Aquí se incluye información como el identificador del usuario (sub) y la fecha de expiración del token.
Signature: Se genera tomando el header y el payload, y firmándolos con una clave secreta para garantizar la integridad y autenticidad del token.
Cada parte está codificada en Base64Url.
Hola!
Para los que tienen curiosidad de como funciona internamente la parte stateless de los JWT.
1. ¿Qué es "stateless"?
Cuando decimos que JWT es stateless, significa que el servidor no guarda información sobre el estado de la sesión del usuario. El servidor no almacena el token ni mantiene un registro de sesiones activas, como sí sucede con una sesión tradicional en la que el servidor guarda una "sesión" en su base de datos o en memoria.
2. ¿Entonces, quién guarda el token?
La respuesta: el cliente (es decir, el navegador o la aplicación del usuario).
El flujo típico es así:
El usuario inicia sesión y el servidor crea un JWT firmado y lo envía al cliente.
El cliente guarda ese token, normalmente en la memoria de la aplicación, en el almacenamiento local (localStorage) o en una cookie.
Cada vez que el cliente quiere acceder a una ruta protegida, adjunta el token en el encabezado de la petición (por ejemplo, en Authorization).
El servidor, al recibir este token, lo valida (verifica la firma) y, si es válido, otorga acceso al usuario.
Mi resumen:
Los JWT son el reemplazo o la versión mejorada de las cookies, las cuales se alojaban en el servidor en memoria o en una base de datos, el problema surge al querer consumir varios servicios(sistemas distribuidos) o hacerlo desde algún dispositivo móvil. Se crean estos tokens, los cuales son stateless y contienen toda la información encriptada y firmada para mayor seguridad.
JWT
<u>Que es?</u>
En el contexto de la Autentificación y autorización, primero nos autenticamos ante un guardián, como por ejemplo utilizando Passport.js y sus métodos de login. Sin embargo, ¿Cómo gestionamos los permisos una vez autenticados?
Anteriormente, se empleaban cookies para manejar las sesiones. Estas cookies contenían la información de inicio de sesión que se enviaba al backend para su verificación. El problema surgía cuando usábamos múltiples nodos; por ejemplo, si el nodo A almacenaba la información de sesión de un usuario y el cliente se conectaba al otro día al nodo B, este último no tendría acceso a la sesión y podría cerrarla involuntariamente.
Es aquí donde entra JWT (JSON Web Token). Esta herramienta nos proporciona un token de acceso que normalmente se guarda en el local storage del cliente. El token contiene información sobre los permisos del usuario en la aplicación y tiene una duración definida por nosotros. Una vez que expira, se cierra la sesión, lo que obliga al usuario a iniciar sesión nuevamente para obtener un nuevo token.
La estructura de un JSON Web Token se divide en tres partes:
- **Header**: Indica el algoritmo de encriptación utilizado.
- **Payload**: Contiene la información encriptada, como los detalles del usuario.
- **Verify Signature**: Proporciona una clave única para la verificación. Esta clave nunca debe ser expuesta y solo debe ser manejada por el backend.