JWT – JSON Web Token

En 10 minutos o menos

JWT es una cadena de texto que tiene tres secciones, las cuales son una cabecera, un contenido y una firma, que estan codificadas cada una por separado en base64 y cada sección esta dividida por un punto. Tiene la siguiente apariencia

base64(cabecera).base64(contenido).base64(firma)

La codificación en base 64 es para garantizar el correcto funcionamiento en la web atraves de diferentes clientes y servidores evitando problemas de codificación de caractares y problemas con saltos de linea.

Un JWT se ve de la siguiente manera

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Y si lo decodificamos utilizando una herramienta como https://jwt.io/ obtendremos:

Contenido

    Estructura en Detalle

    La especificación de JWT puede encontrarse en el siguiente enlace https://datatracker.ietf.org/doc/html/rfc7519, a continuación se explicará a groso modo cada una de las partes teniendo en cuenta información de la referencia.

    Cabecera (Header)

    Es un JSON que conmunmente contiene 2 atributos, el algoritmo utilizado (alg) para firmar y el tipo de token (typ), el cual siempre va a ser JWT. Existen una gran variedad de algoritomos que se pueden utilizar para encryptar el token, estos se encuentran en la especificacion de JWA (JSON Web Algorithms) https://datatracker.ietf.org/doc/html/rfc7518

    Cuerpo (Payload)

    Este tambien es un JSON y en el contexto de JWT los atributos (par de nombre y valor) son conocidos como Claims y se tienen de 3 tipos, los cuales son registrados, publicos y privados. Su objetivo es pasar información que se considera publica (debido a que el body no se encripta).

    Claims Registrados

    Estos son los atributos que vienen predefinidos en el estandar y por lo tanto solo deben ser usuados según el estandar lo recomienda y ninguno de los otros tipos de claims (públicos o privados) deben repetirlos.

    Claims Públicos

    Son atributos registrados y manejado por IANA y tienen un proceso para ser incluidos como calim publicos. Estos pueden encontrarse https://www.iana.org/assignments/jwt/jwt.xhtml

    Claims Privados

    Son atributos definidos a necesidad de quien desarrolle y puede ser cualquier valor siempre y cuando no se colapse con los calims registrados o publicos. un ejemplo podria ser esUsuarioAdmin : true/false.

    Firma (Signature)

    La firma esta compuesta por la cabacera y el cuerpo mas una llave privada y un algoritmo de encriptación. De esta forma se asegura que cuando el token es trasmitido por diferentes lugares, nuevamente retornado y teniendo la llave privada, se puede verificar que el contenido no ha sido alterado y que el token es valido. Una firma se generaria de la siguiente forma

    AlgoritmoEncriptacion( 
      base64(cabecera).base64(cuerpo),
      secreto
    )

    Otros Detalles

    • Un JWT usualmente debe tener una fecha de creación el cual se deberia de registrar en el claim iat (issued at), el cual es el número de segundos desde 1970-01-01T00:00:00Z UTC.
    • Un JWT deberia de tener una fecha de expiración que se manejaria en le claim exp. Tener una fecha de expiración ayuda a mejorar la seguridad de las aplicaciones y se considera una buena practica. Mientras mas tiempo de vida tenga un token, mayores posibilidades de que este caiga en manos equivocadas.
    • La cabecera y el cuerpo no se encuentran encriptados, lo cual permite a cualquiera que tenga el token poder decodificarlos en base 64 y obtener los valores, por lo tanto no se debe pasar información confidencial en ninguno de ellos.
    • Si se asegura con un par de llaves (publica y privada), quien emite la firma utiliza la llave privada y solo comparte la llave pública, de esta forma se incrementa la seguridad y no se necesita de un secreto compartido.

    Usos Comunes

    Usualmente es utilizado para la autorización de un usuario a una app o servicio, por lo que se utiliza como alternativa a las sesiones entre clientes y servidores, asegurar servicios web e incluso como una herramienta complementaria en frameworks como lo es OAUTH 2.0.

    Reemplazando Cookies

    Flujo Tipico de Sesión

    Un flujo normal de sesion se ve de la siguiente forma

    1. El usuario desde el navegador ingresa las credenciales de acceso (usuario y contraseña) y las envia al servidor.
    2. El servidor verfica que las credenciales son correctas y crea una sesion que queda en el servidor.
    3. El cliente recibe un identifcador que se relaciona a la sesion en el servidor y la guarda en un cookie.
    4. el cliente envia una solicitud con la información de la cookie al servidor
    5. El servidor verifica la sesion y si es valida retorna el recurso protegido.

    Flujo con JWT

    En este flujo el servidor tiene que guardar la información de la sesion.

    Un flujo con JWT se ve de la siguiente forma

    1. El usuario desde el navegador ingresa las credenciales de acceso (usuario y contraseña) y las envia al servidor.
    2. El servidor verfica que las credenciales son correctas y crea un JWT.
    3. El cliente recibe JWT.
    4. el cliente envia una solicitud con el JWT
    5. El servidor verifica que el JWT y si es valida retorna el recurso protegido.

    Ventajas de JWT frente a Sesiones

    Ambos flujos son practicamente iguales, la diferencia radica en que si se utiliza JWT, no es necesario guardar ningun rastro del cliente en el servidor.

    Si tenemos múltiples aplicaciones o servicios, el usuario solo se autentifica una vez y cada de una las aplicaciones de confianza que pueda validar el token lo puede realizar sin volver a preguntar por las credenciales nuevamente, lo cual seria mas complejo con la autentificación con sesión debido a que se tendréa que duplicar la sesión en multiples servidores o aplicaciones y adicionalmente las cookies suelen tener restricciones para ser utilizadas entre diferentes dominios.

    Asegurando Servicios Web

    Es poco practico pero simplemente compartiendo un token a las personas o aplicaciones que simplemente queremos que tengan accesso al servicio y tratandolo como un secreto, podemos aegurar nuestros servicios web. Es preferiblemente utilizar algun estandar o framework como OAUTH 2, en el cual mucha gente lo revisa y mejora cada dia.

    Suponiendo que le damos a un cliente un JWT valido (puede ser creado por consola o con alguna herramienta ), luego el cliente lo agrega en las solicitudes, se verifica en el servidor y se retorna la información protegida.

    Complemento de OAUTH 2

    En oauth 2 existen muchos tipos de flujos (grant types), en los cuales se obtiene un token de acceso, este token de acceso podria ser un JWT en el cual los recursos podrían verficar el token sin necesidad de llamar cada vez al servidor de autorización para verificar su valides.

    Client Credentials Grant

    En este flujo simplemente la aplicación cliente envia el client id y client secret, y el servidor de autorización retorna un token de acceso.

    Ahora con el token, simplemente queda consumir el servicio

    Sin JWT

    Cada vez que se realiza una solicitud al recurso, este tiene que validar el token en el servicio de autorización.

    Esto puede ser una penalización de rendimiento dependiendo el proyecto y la cantidad de clientes que utilicen el servidor de autorización.

    Con JWT

    Con JWT podemos validar el token en el recurso sin necesidad de ir al servidor de autorización cada vez. Obviamente para poder validar el token en el recurso, tanto el servidor de autorización como el recurso tienen que compartir la llave privada con la que se firma el token. El flujo se veria asi

    Conclusiones

    JWT es una idea simple, pero poderosa en la cual a traves de encriptación podemos hacer mas optimas las aplicaciones.

    Muchas gracias por leer.

    Commentarios

    Leave a Reply

    Your email address will not be published. Required fields are marked *