En este artículo analizaremos qué es JWT y cuáles son sus utilidades, además de describir las diferentes cuestiones referidas a la seguridad que provee su uso y las alternativas que hay a la hora de firmarlas.
Índice de temas
¿Qué es JWT
JSON Web Token o mejor conocido por su abreviatura JWT, es un objeto de Java script creado con el propósito de transmitir información de forma segura y efectiva entre un determinado emisor y su respectivo receptor.
Por lo general, las dos partes que realizan las transferencias de datos mediante JWT tienen una relación de cliente y servidor.
El servidor, al recibir los datos enviados a través de un JWT, puede verificar que estos sean confiables porque no es posible modificarlos una vez que fueron firmados y encriptados.
¿Para qué sirve?
Es una herramienta de estándar abierto, es decir que está a disposición del público para el cumplimiento de una tarea específica.
Sirve para esparcir información y la identidad de un usuario sin tener que preocuparse por la seguridad, ya que la misma se transmite firmada de forma virtual gracias a las características propias del JSON Web Token.
En general, es utilizado por aplicaciones para validar la identidad de un determinado usuario.
Es que de eso se trata el JWT, de garantizar la propiedad de los datos y no específicamente la seguridad del contenido que en algunos casos puede ser descifrado con un debugger online.
Sin embargo, como analizaremos en profundidad más adelante, el contenido del mensaje también puede estar cifrado. Eso dependerá de si se trata de un JSON Web Signature (JWS) o de un JSON Web Encryption (JWE).
El hecho de estar firmada permite que la parte receptora pueda confiar plenamente en la información que recibe debido a que está verificada.
Por otro lado, como anticipamos, es una forma segura de corroborar si ha sido el remitente correcto quién ha enviado los datos o si, por el contrario, los mismos fueron modificados.
Una ventaja del JWT es que no es de gran tamaño, por lo que existe una variedad de espacios desde los que se puede utilizar.
Puede ser usado, por ejemplo, en sitios URL que son aquellos que conducen a los usuarios hacia una página web específica, en los parámetros de respuesta POST e incluso dentro de un Header HTTP.
Una característica propia de los JWT que lo distingue de otros tokens de seguridad existentes es que están formados por demandas o su palabra en inglés con la que suele denominarse a este concepto, claims.
Como hemos mencionado, dichas demandas están insertas en el contenido del mensaje enviado y protegidas por la seguridad que proveen los JWT.
Para obtener una definición más compacta, podemos decir que un JWT consiste en un grupo de demandas que se transfieren con la protección de una firma que garantiza su autenticidad.
Ventajas del uso de JWT
La implementación de un token web JSON brinda múltiples ventajas:
Autenticación sin estado
En primer lugar, como los JWT son autónomos y abarcan toda la información necesaria, se erradica por completo la necesidad de contar con un almacenamiento de sesiones del lado del servidor. En otras palabras, se puede alcanzar la autenticación de datos en aplicaciones web sin estado.
Autenticación entre dominios
Por otra parte, los JSON web tokens pueden utilizarse en diferentes dominios. Por esta razón, son complementos ideales para ejecutar escenarios de inicio de sesión únicos (SSO, por su sigla en inglés).
Rendimiento
A su vez, otro de los beneficios de utilizar JWT es que estos objetos permiten optimizar el rendimiento de los servicios web de una plataforma debido a que no requieren la consulta a una base de datos para la autenticación del usuario en cada solicitud.
Escalabilidad
Asimismo, estos JWT pueden escalarse muy fácilmente entre diferentes servidores. La razón es simple: al no tener estado, no deben compartir datos de sesión.
Token JWT, ¿Que es?
En este apartado y con el objetivo de poder entender mejor a qué nos referimos cuando hablamos de JWT nos propondremos hablar del token propiamente dicho.
En primer lugar, es necesario definir qué es un token en general para luego comprender las características que distinguen al Token JWT.
Es por esto que explicaremos el concepto de tokenización que se refiere a un proceso en el cual se sustituyen determinados datos sensibles, es decir, aquella información que se quiere transmitir, por otros datos no sensibles equivalentes.
Lo central de este concepto es que aquellos datos no sensibles no tienen un valor o significado, sino que equivalen a la información que sí es importante.
De esta manera, es posible proteger la información sensible que debemos transmitir debido a que viaja a través de datos que no tienen importancia alguna por sí solos.
En particular, el token JWT se trata de un cuerpo de texto separado por un punto en tres partes codificadas en base64, un grupo de esquemas de codificación de binario. Es decir que la forma de un token JWT es la siguiente: aaaaa.bbbbbb.cccccc.
Para que se pueda observar el contenido del token, es necesario que se pueda descodificar si este consta de una firma y cifrado. La manera de lograr esto es a través de una contraseña común o privada.
En algunos casos, los JWT pueden estar firmados de formas menos seguras cuando no sea necesario proteger la información, por lo que en esa situación al descifrar el código de base64 se podrá leer el contenido del mensaje.
Firma de un token JWT y seguridad
Tal como adelantamos, los JWT pueden estar firmados de distintas maneras. La seguridad y el nivel de codificación que tenga el token pueden variar acorde a la clase de firma que tenga.
La firma de un token JWT es justamente lo que lo hace confiable y seguro. En definitiva, es por la firma que es posible verificar que el remitente es el que esperamos de forma original y que el contenido del mensaje es el que debe ser.
De esa forma, se evita que el mensaje sea modificado en el medio de la transmisión incrementando la seguridad de la información.
La firma está compuesta por la codificación base64 del header y del payload que son parte de la propia estructura del JWT que analizaremos más adelante. Se construye con un código de autenticación de mensajes y el algoritmo SHA de 256 bits.
El algoritmo Secure Hash Algorithm o conocido por sus siglas SHA es una función de hash criptográfica que constituye un estándar federal de procesamiento de la información en los Estados Unidos.
Las funciones hash tienen como principal objetivo proteger la confidencialidad de una clave y de alguna manera impedir que la efectivización de un ataque cibernético que busque robar una determinada base de datos.
Ahora bien, esta codificación solo será efectiva si se utiliza una clave secreta que debe ser conocida solamente por la aplicación en cuestión. De hecho, es la propia aplicación la que establece dicha clave.
Es así como nos daremos cuenta si alguien ha introducido información no deseada en el camino. Cuando comprobemos la autenticidad de la firma, si esta no es correcta, entonces es necesario denegar la petición de que se trate.
Por eso es importante recordar que al trabajar con JSON Web Token siempre se debe verificar la firma con el propósito de saber si el token es efectivamente válido.
Hay tres tipos de firmas de un JWT que dependen de cuan confidenciales sean los datos que se estén transmitiendo.
En primer lugar, en el estadio más bajo de la protección de los datos puede no generarse ninguna firma. Esto ocurrirá si dentro de la estructura del JWT, más específicamente en el header se agrega la palabra none.
Así el payload, que como analizaremos más adelante es la parte del Token JWT que contiene los datos, podrá ser leído de forma clara una vez que se descifre el código base64.
Además, el hecho de no tener protección alguna hará que no se pueda verificar si quien envía el mensaje es el remitente original ni tampoco si el mensaje ha mantenido su forma natural o si ha sido modificado.
Este tipo de firmas es utilizado mayormente para datos que no tienen la necesidad de ser protegidos de una forma muy compleja.
Luego, en un estadio intermedio de seguridad, encontramos los token firmados mediante la JSON Web Signature.
Con esta firma, se puede verificar que el remitente sea el deseado y que el mensaje no haya recibido cambios.
De todas formas, comparte con la seguridad descrita previamente el hecho de que el mensaje contenido en el payload puede ser leído solamente con descifrar el código 64.
Por último, tenemos la firma que más protege a la información de nuestro JWT. Además de utilizar una JWS, se puede encriptar el mensaje contenido en el payload a través de JSON Web Encryption, conocido por sus siglas JWE.
Es aquí donde se reúne el máximo nivel de seguridad en el cual se puede verificar el remitente, la autenticidad y originalidad del mensaje y por último el mensaje del payload queda encriptado por lo que no será posible leerlo luego de descifrar el código base64.
Ciclo de vida de un Token JWT
Hemos visto hasta aquí cuáles son las características principales de un JWT, hemos descrito cómo funciona la firma de ellos y cómo afecta eso a la seguridad.
En este apartado, nos limitaremos a describir el ciclo de vida de un token JWT y su relación con un proceso de autenticación. Recordemos que una de las funciones principales del token es verificar la identidad de un determinado usuario.
Sin embargo, cuando nos referimos a JSON Web Token no estamos hablando de un estándar de autenticación, sino de un estándar que permite el intercambio de información entre dos partes.
Habiendo aclarado estos puntos, procederemos a explicar el ciclo de vida de un token JWT para lograr una correcta autenticación de la identidad de un usuario.
En primer lugar, debemos enviarle al cliente una petición POST el cual deberá ser respondido con el usuario y la contraseña a fin de que se concrete el proceso de login.
Si el usuario y contraseña que el cliente enuncia son correctos se genera el token que será utilizado por la aplicación cliente para solicitar los recursos que le hicieran falta.
Una vez que el usuario comienza a hacer peticiones, el servidor comprobará la validez del token verificando la firma del mismo.
Recordemos que una de las ventajas que provee la firma de un token es la posibilidad de verificar si el emisor es el deseado y si el mensaje no fue modificado en el camino.
Por otro lado, también sabemos que dentro de la estructura del token, en el payload podemos observar los datos del usuario que ha formulado la solicitud.
Pues bien, una vez que el servidor haya verificado la firma y comprobado la autenticidad del token, podrá obtener el recurso solicitado y responder con el mismo de forma segura para que pueda ser utilizado por el cliente.
¿Cuándo utilizar JWT?
A la hora de mencionar las características propias de un JWT es necesario detenernos en la cuestión del uso. Más específicamente, cuándo es conveniente utilizar JWT y de qué manera nos puede servir.
Pues bien, hay dos aspectos centrales que hacen a la utilidad de esta herramienta. Por un lado, la autenticación API y por el otro la autorización de servidor a servidor.
Es que por las características de un JWT es que se vuelve un estándar ideal para la autenticación de API.
El hecho de no poseer un gran tamaño y la necesidad de un paquete ligero. Recordemos que la incluiremos en cada solicitud que se haga a nuestra API REST.
Pero lo que más destaca a JWT es la seguridad de que nadie va a poder falsificar la identidad del usuario en el camino, algo que también hace que sea beneficioso para este tipo de transferencia de datos y autenticaciones.
Es también una herramienta que no mantiene ninguna sesión en particular, por lo que solo el hecho de estar firmado con un secreto generado y solo conocido por la API REST hace que podamos confiar en la identidad del usuario sin otro control.
Por otro lado, el uso de JWT provee más seguridad ya que no es necesaria la utilización de cookies lo cual permite prevenir ataques que vulneren los datos e información del usuario.
¿Qué es JWT y cuáles son sus 3 componentes principales?
Tal como hemos ido describiendo a lo largo del artículo un JWT es un proceso por el cual se verifica la identidad de un usuario determinado y su relación con la propiedad de determinados datos.
Se trata de una cadena de información que está firmada de forma criptográfica, lo cual le da la seguridad necesaria para poder confiar en los datos que lleva consigo.
Dentro de su estructura podemos encontrar varios componentes, por lo que mencionaremos cuales son los tres principales y los describiremos en detalle más adelante.
Al tratarse de una cadena de información, la misma está separada por un punto y consta de un header, payload y signature.
¿Qué es el estándar JWT?
Cuando dimos la definición principal de un JWT dijimos que era un estándar abierto, lo cual quiere decir que es abierta al público y que cualquiera puede tener acceso a él.
Dicho estándar fue propuesto por IETF, una organización creada en 1986 que tiene el objetivo de contribuir a la ingeniería de internet e innovar en materia de seguridad y encriptación de datos e información.
El estándar JWT obtuvo el nombre de RFC 7519 y constituye una forma segura de transmitir información y almacenar objetos JSON entre diferentes aplicaciones.
Se trata de un estándar que debe ser conocido por alguien que está incursionando en materia de desarrollo de la tecnología y en la seguridad de datos.
Esto es debido a que no solo es útil para el intercambio de información cómo mencionamos en el párrafo anterior, sino porque se trata además de una forma muy útil de autenticación de un usuario.
El estándar JSON Web Token, además es una especie de una familia conocida como JOSE (JSON OBJECT SIGNING AND ENCRYPTION).
Dicha familia está compuesta por otras diferentes herramientas, algunas que ya hemos descrito anteriormente.
En primer lugar, está conformada por el propio token al cual no estamos refiriendo (JWT).
Por otro lado, también conforman esta familia el JSON Web Signature (JWS) que es esencialmente la firma del token y el JSON Web Encryption que es la encriptación de la firma, la cual además utilizamos cuando queremos que no sea posible descifrar el mensaje contenido en el payload.
Debemos mencionar también al JWK y al JWA que son las claves y los algoritmos para la firma respectivamente.
Pero además de validar la identidad de un usuario, el estándar JWT también puede estar formado por claims o privilegios que forman parte de la comunicación entre cliente y servidor.
Estructura del JWT: Header, Payload y Signature
Habíamos mencionado con anterioridad la existencia de tres componentes básicos que hacen a la propia estructura del JWT. Ellos son el Header, Payload y Signature.
Recordemos que un JSON Web Token está formado por una cadena de información que se divide en tres partes. Dichas partes encuentran su límite y separación con un punto. Pues cada parte es uno de estos elementos esenciales que hacen a la efectividad del token.
Header
En primer lugar, dentro de la cadena de información tenemos el header que es básicamente un objeto JSON cuyo rol es el de destacar el tipo de token del cual se trata y el algoritmo de encriptación que tenga la firma.
Al observar el header podremos comprender que existen tres tipos de algoritmos que son HMAC, SHA 256 y RCA, de los cuales cualquiera de los tres puede ser el que forme parte del JWT.
Payload
Luego del header viene un punto al cual le sigue el payload. El payload, la segunda parte del JWT, es también un objeto JSON.
Es en el payload en donde se encuentra el contenido del token y en donde también podemos encontrar las claims o demandas que son transferidas.
Dentro del payload y las claims podemos observar fácilmente diferentes tipos de información.
Por un lado, si observamos la palabra sub, que refiere a una abreviación de subject, podremos saber cuál es la entidad a la que pertenece el JWT.
Luego es posible observar la palabra Iat que funciona como una abreviación de issued at y nos ubica en el tiempo. Es decir, nos da información acerca de la fecha y la hora en la que el JWT fue utilizado.
Por último, tenemos las letras exp referidas a expiration. Estas últimas nos indican el tiempo de uso del JSON Web Token, en otras palabras nos van a determinar cuál es la fecha de expiración del mismo.
Es menester mencionar que también el payload puede estar conformado por reivindicaciones enviadas de un usuario cliente a su servidor.
Es facultad de quien las envía definir si las mismas serán públicas o privadas, pero debe especificarse bien esta calidad porque de otro modo será difícil realizar la diferenciación de ellas.
Vale aclarar que en el caso de que exista una demanda duplicada, la lectura se hará como la de un objeto JSON normal y el valor que se tomará es el último asignado a su respectiva clave.
Signature
Por último, para completar la estructura del JWT, nos referiremos a Signature. Signature está formado por la firma del header codificado, del payload codificado, el secreto y el algoritmo que se ha establecido en el header.
Es signature o firma en español, el elemento clave en materia de seguridad de las JWT ya que gracias a ella se puede confiar plenamente en que el emisor haya sido quien dice ser y que el mensaje se ajuste tal cual fue enviado sin interrupciones no deseadas en el camino.
La estructura del JWT lo hace una herramienta compacta, lo cual es un beneficio ya que esa característica le permite que se pueda utilizar de distintas formas como en una URL o HTTP.
Usos e implementaciones
En cuanto al uso del estándar JWT podemos remarcar que su implementación se da en la autenticación de las API.
Tan confiable es este token que incluso Google las utiliza para que se puedan autenticar en sus API.
Además, se trata de un estándar aceptado por una amplia variedad de lenguajes y contar con su disponibilidad es muy sencillo.
Por estas características y por tener la cualidad de poder contar con una verificación y una encriptación, con el paso del tiempo ha ido ganando terreno en el ámbito del desarrollo de aplicaciones.
Hay también otras situaciones en las cuales utilizar JWT puede ser beneficioso como es el caso de la autenticación de SPA. Cabe recordar que JWT no utiliza una base de datos por su alta confiabilidad en la seguridad de los datos que se le envían al cliente.
En conclusión, a lo largo del artículo hemos hecho una síntesis de lo que es JTW y de sus utilidades.
Se trata de una herramienta que tiene un enorme potencial en el campo del desarrollo de aplicaciones y que es muy utilizada para verificar la identidad de los usuarios.
Sin ninguna duda, es una necesidad conocer sobre ella si se quiere aprender sobre API, aplicaciones y seguridad de datos.
Actualmente, existen diferentes implementaciones de JWT, entre las cuales se destacan:
C
Se puede implementar JWT en C, el famoso lenguaje de programación nacido en los 60. Toda la información se encuentra en este repositorio.
Common Lisp
Además, también se puede hacer uso de un JSON web token en Common Lisp, el lenguaje perteneciente a la familia Lisp. Toda la información se encuentra en este repositorio.
Go
Por otra parte, JWT está disponible para Go, el lenguaje desarrollado por Google inspirado en C. Toda la información se encuentra en este repositorio.
.NET
Asimismo, el framework de Microsoft .NET también incluye la posibilidad de aplicar JWT. Toda la información se encuentra en este repositorio.
Perl
Perl es otro de los lenguajes que sirve para desarrollar aplicaciones con JSON web tokens. Toda la información se encuentra en este repositorio.
Perl6
También conocido como Raku, Perl6 permite implementar JWS de forma práctica y efectiva. Toda la información se encuentra en este repositorio.
Además de estas, existen otras implementaciones muy utilizadas como PHP, Python, Ruby, Rust, Scala, Clojure, Elixir, Erlang, Lua, Java y JavScript.
¿A qué se le llama JWT Python?
JWT Python, conocido también como PyJWT, es una biblioteca de Python que sirve para codificar y decodificar tokens web JSON. Para instalarla, sólo basta con llamar a la función “pip”, de modo que la línea de código quede así:
- $ pip install pyjwt
Por otra parte, si tu objetivo es codificar o decodificar tokens mediante algoritmos de firma digital, como RSA o ECDSA, tendrás que instalar la biblioteca de criptografía de la siguiente forma:
- $ pip install pyjwt[crypto]
En cualquier caso, siempre se recomienda analizar a fondo el funcionamiento de la biblioteca PyJWT mediante su sitio web oficial.
Paso a paso: cómo crear un token web JSON (JWT)
Crear un token web JSON puede ser una tarea algo compleja, pero todo se resume a las tres partes principales de la estructura: encabezado (header), carga útil (payload) y firma (signature).
Crear un header
El header incluye la información sobre cómo hay que calcular la firma JWT. Este elemento también es un objeto JSON:
- Header = {“alg”: “HS256”, “typ”: “JWT”}
Se utilizará al crear la firma. HS256 significa HMAC-SHA256; para su cálculo, solo se necesita una clave secreta.
Crear un payload
El payload será la carga útil que se guarda dentro del JWT. En este ejemplo, el servidor de autenticación crea un JSON web token con información sobre el ID del usuario:
- Payload = {“userId”: “b08f86af-35da-48f2–8fab-cef3904660bd”}
Para el payload, existen algunas aplicaciones estándar:
- iss (emisor): define la aplicación desde la que se envía el token.
- sub (asunto): define el tema del token.
- exp (tiempo de expiración): consiste en la vida útil del token.
Establecer una signature
El algoritmo base64url codifica el encabezado y la carga útil anteriormente creados y concatena las cadenas codificadas mediante un punto:
- Header: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
- Payload: eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ
- Signature: -xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM
Combinar los tres componentes
Por último, sólo resta crear el JWT con los tres elementos:
- const token = encodeBase64Url(header) + ‘.’ + encodeBase64Url(payload) + ‘.’ + encodeBase64Url(signature)
Artículo publicado originalmente en 25 Ene 2023