Comprensi贸n de los tokens web JSON (JWT)

    Durante mucho tiempo, la autenticaci贸n de usuarios en la web consisti贸 en almacenar algunos datos muy simples (como una identificaci贸n de usuario) en el navegador del usuario como una cookie. Esto funcion贸 bastante bien (y todav铆a lo hace para muchas aplicaciones), pero a veces se requiere m谩s flexibilidad.

    Tradicionalmente, para obtener esta flexibilidad, ten铆a que almacenar ‘estado’ en el servidor, lo que podr铆a decirle cosas como qui茅n es el usuario, qu茅 tipo de permisos tiene, etc. Para almacenar estos datos, generalmente ten铆a que tener un dato dedicado almacenar, como Redis o una base de datos, que se sumaba a la complejidad de su aplicaci贸n.

    En los 煤ltimos a帽os, ha aparecido un nuevo est谩ndar abierto que est谩 siendo adoptado cada vez m谩s por algunos de los principales sitios web y aplicaciones. Este est谩ndar es el Token web JSON (JWT). A lo largo de este art铆culo, le mostraremos c贸mo funcionan y, lo que es m谩s importante, por qu茅 realmente querr铆a usarlos.

    Nota: El est谩ndar JWT se vuelve un poco m谩s complejo con los JWS y JWE est谩ndares, por lo que para este art铆culo nos centraremos solo en lo que se especifica para JWT.

    驴Por qu茅 utilizar JSON Web Tokens?

    Con las cookies de sesi贸n cl谩sicas que se utilizan en la mayor铆a de los sitios web, usted almacena un token en el lado del cliente en una cookie del navegador (normalmente), que luego se utiliza para buscar los datos de su sesi贸n en el lado del servidor. Esto funciona bien para la mayor铆a de los sitios web simples, pero debe adaptarse a todos estos datos adicionales del lado del servidor con alg煤n tipo de almac茅n de datos.

    Por otro lado, con los JWT, en cambio, puede almacenar los datos de esta sesi贸n en el lado del cliente sin tener que preocuparse de que sean manipulados por el usuario u otro tercero, gracias a que est谩 firmado por el servidor. Su cookie de sesi贸n cl谩sica tambi茅n est谩 firmada / encriptada, pero al menos ahora los datos residen con el usuario.

    El almacenamiento del lado del cliente de datos tambi茅n reduce cierta complejidad en el lado del servidor, ya que ya no necesita un almac茅n de datos de baja latencia para almacenar y recuperar datos de sesi贸n con frecuencia.

    Tambi茅n obtiene un poco m谩s de flexibilidad con el tipo de datos que almacena con los JWT. Dado que los datos est谩n en formato JSON, puede utilizar estructuras de datos profundamente anidadas. Claro, esto tambi茅n es posible con el lado del servidor de datos de sesi贸n, pero nuevamente, con los JWT no es necesario lidiar con otra base de datos.

    Entonces, adem谩s de reducir la complejidad y aumentar la flexibilidad, 驴por qu茅 m谩s usar铆a un JWT? 驴Qu茅 tipo de datos se almacenan normalmente all铆? El estandar (RFC 7519) no especifica un tama帽o m谩ximo para el token, por lo que, en teor铆a, puede almacenar tantos datos como desee, siempre que no exceda el tama帽o m谩ximo de su medio de almacenamiento. Sin embargo, esto no es realmente recomendable ya que se supone que los JWT son lo m谩s compactos posible.

    La mayor铆a de las aplicaciones con las que me he encontrado se beneficiar铆an de tener al menos la siguiente informaci贸n:

    • Identificaci贸n de usuario (un UID, correo electr贸nico, etc.): bueno para buscar f谩cilmente m谩s detalles sobre el usuario en su base de datos
    • Marca de tiempo de vencimiento del token: en la mayor铆a de los casos, los tokens no deber铆an durar para siempre y el usuario deber铆a tener que volver a autenticarse
    • ID de JWT: bueno para revocar un JWT, lo que obliga a un usuario a tener que volver a iniciar sesi贸n

    Por supuesto, puede tener mucha m谩s informaci贸n que esta en su token, pero este suele ser un buen punto de partida para una nueva aplicaci贸n.

    Tambi茅n se recomienda que los JWT se almacenen en un almacenamiento local y no en cookies, aunque tambi茅n se pueden usar cookies. Esta es la forma recomendada ya que Uso compartido de recursos entre or铆genes (CORS) no utiliza cookies de forma predeterminada. En su lugar, debe enviar un JWT en el encabezado ‘Autorizaci贸n’ utilizando el esquema ‘Portador’.

    Ahora veamos de qu茅 se compone un JWT en la siguiente secci贸n.

    Estructura

    Un token web JSON se compone de tres secciones: un encabezado, una carga 煤til y una firma. Tanto el encabezado como la carga 煤til almacenan datos en formato JSON, que es Base64-encoded, mientras que la firma se crea alimentando el encabezado y la carga 煤til a trav茅s de un algoritmo de firma (que se especifica en el encabezado) junto con un secreto. Con esta firma, se puede verificar la autenticidad del token y se puede verificar que ning煤n tercero no autorizado haya falsificado datos.

    La estructura general del token se parece a esto:

    hhhhhhhh.ppppppppp.sssssssss
    

    D贸nde h es el encabezado, p es la carga 煤til, y s es la firma.

    El encabezado

    La secci贸n de encabezado est谩 destinada a proporcionar informaci贸n importante sobre el token. Por lo general, le indicar谩 el tipo (“tipo”) de token que es (que recomendamos usar siempre “JWT”) y el algoritmo utilizado para firmar el token:

    {
        "typ":"JWT",
        "alg":"HS256"
    }
    

    En este ejemplo, el encabezado afirma que se utiliz贸 “HS256” o HMAC-SHA256 para firmar el token.

    Si su JWT es un poco m谩s complejo y tiene firma o encriptaci贸n anidada, entonces tambi茅n debe usar el par谩metro de encabezado “cty” con un valor de “JWT”, de lo contrario se puede omitir. Por otro lado, un JWT sin firma o cifrado debe tener un valor “alg” de “ninguno”.

    La carga 煤til

    La carga 煤til del token es donde realmente puedes transmitir tu informaci贸n a la aplicaci贸n. Para intentar hacer que los JWT sean m谩s interoperables entre varias aplicaciones, se han establecido algunos est谩ndares para definir qu茅 y c贸mo se comunican ciertos datos. Esto se hace mediante “reclamaciones”. Hay tres tipos de reclamos definidos por JWT:

    • Reclamaciones registradas: estas son reclamaciones registradas en el Reclamaciones de token web JSON de IANA registro. No es necesario configurar ninguno de estos, pero se dan como punto de partida para aumentar la interoperabilidad entre aplicaciones. Algunos ejemplos son el emisor (“iss”), el asunto (“sub”), la audiencia (“aud”) y el tiempo de vencimiento (“exp”). Se prefieren los nombres de reclamo cortos para limitar la longitud del token.
    • Reclamos p煤blicos: estos son reclamos que se pueden definir “a voluntad”, lo que significa que no hay restricciones expl铆citas. Para evitar colisiones entre nombres, debe registrarlos en el registro de reclamaciones de IANA JSON Web Token o utilizar un nombre resistente a colisiones.
    • Reclamaciones privadas: esta suele ser la informaci贸n m谩s espec铆fica de su aplicaci贸n. Si bien una reclamaci贸n p煤blica puede contener informaci贸n como “nombre” y “correo electr贸nico”, las reclamaciones privadas ser铆an m谩s espec铆ficas, como “ID de usuario” o “alcance de autorizaci贸n”.

    Si bien creo que es importante adherirse al est谩ndar JWT en lo que respecta a las afirmaciones de nombres, no est谩 obligado a utilizar ninguno de los que hemos mencionado aqu铆 (o cualquier otro especificado en el est谩ndar). En su lugar, puede usar los suyos, pero no espere que sus tokens tengan interoperabilidad con otras aplicaciones de terceros.

    La firma

    La firma se crea utilizando la codificaci贸n Base 64 (m谩s sobre esto a continuaci贸n) del encabezado y la carga 煤til, que se concatenan con un punto (‘.’). Para que esta firma funcione, se debe utilizar una clave secreta que solo sea conocida por la aplicaci贸n de origen.

    El pseudoc贸digo para crear la firma se ver铆a as铆:

    unsignedToken = base64Encode(header) + '.' + base64Encode(payload)
    signature = HS256('your-secret-key', unsignedToken) 
    

    Normalmente, el algoritmo criptogr谩fico utilizado es HMAC con SHA-256 o un RSA firma con SHA-256.

    Adem谩s de esto, existe otro est谩ndar que especifica muchos m谩s algoritmos para usar en la autenticaci贸n y el cifrado basados 鈥嬧媏n tokens. Este es el Algoritmo web JSON (JWA) est谩ndar. Si necesita m谩s opciones sobre cifrado y firma, consulte esto.

    Codificaci贸n JWT

    En esta secci贸n, veremos un ejemplo real de c贸mo tomar nuestros datos JSON y crear un token web a partir de ellos. Aqu铆 est谩n los datos con los que trabajaremos:

    Encabezamiento

    {
      "alg": "HS256",
      "typ": "JWT"
    }
    

    Carga 煤til

    {
      "sub": "123456789",
      "name": "Scott Robinson",
      "awesome": true
    }
    

    Puede recordar de anteriormente en este art铆culo que el token resultante debe tener la forma de:

    hhhhhhhh.ppppppppp.sssssssss
    

    El primer paso es codificar en URL Base64 cada secci贸n. Codificar el encabezado desde arriba nos da lo siguiente:

    base64Header = base64Encode(header)
    // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    

    Hacer lo mismo con la carga 煤til desde arriba produce:

    base64Payload = base64Encode(payload)
    // eyJzdWIiOiIxMjM0NTY3ODkiLCJuYW1lIjoiU2NvdHQgUm9iaW5zb24iLCJhd2Vzb21lIjp0cnVlfQ
    

    Desde aqu铆 necesitamos generar nuestra firma. Como probablemente haya notado en los datos del encabezado, usaremos el algoritmo HS256 para generarlo.

    signature = HS256(base64Header + '.' + base64Payload, 'super-sekret')
    // WwR-0ZlhUBRkBlUBZ6l6lWvBZNGmdAsageRCvry3bY0
    

    Para obtener el token final, juntamos estas tres partes, uniendo cada una con un punto (‘.’), As铆:

    token = base64Header + '.' + base64Payload + '.' + signature
    // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkiLCJuYW1lIjoiU2NvdHQgUm9iaW5zb24iLCJhd2Vzb21lIjp0cnVlfQ.WwR-0ZlhUBRkBlUBZ6l6lWvBZNGmdAsageRCvry3bY0
    

    Esto es bastante sencillo de hacer por su cuenta, pero probablemente no tenga que hacerlo. Todav铆a tengo que usar un lenguaje de programaci贸n que a煤n no tiene una biblioteca para generar tokens JWT como este para usted. Para obtener enlaces a algunas de las bibliotecas m谩s populares, consulte la secci贸n Bibliotecas a continuaci贸n.

    Decodificaci贸n y verificaci贸n de JWT

    Ahora que sabemos c贸mo codificar un JWT, la decodificaci贸n es bastante f谩cil. Comenzamos dividiendo el token por puntos y luego decodificamos cada secci贸n por separado:

    base64Header, base64Payload, signature = token.split('.')
    
    header = base64Decode(base64Header)
    payload = base64Decode(base64Payload)
    
    // Read the header and payload data here
    

    La parte un poco m谩s complicada es cuando necesitamos verificar la firma. Hacemos esto recreando la firma del encabezado y la carga 煤til usando nuestro secreto, y luego verificamos si coincide con la firma que nos dieron. Si no es as铆, entonces el token no es aut茅ntico o se ha alterado de alguna manera.

    computedSig = HS256(base64Header + '.' + base64Payload, 'super-sekret')
    
    if computedSig != signature:
        print('FAILED')
    

    Tenga en cuenta que, en la mayor铆a de los casos, debe verificar el encabezado para ver qu茅 algoritmo se us贸 en la firma, pero podemos omitir esa parte aqu铆 para nuestros prop贸sitos.

    Bibliotecas

    Afortunadamente, no falta soporte para JWT en todos los lenguajes web populares. Aqu铆 hay algunas bibliotecas notables que vale la pena consultar:

    Hay bastantes m谩s que no enumer茅 aqu铆, pero estos son los que encontrar谩 m谩s com煤nmente para el desarrollo de aplicaciones web.

    Conclusi贸n

    Es un peque帽o cambio de la forma tradicional de hacer las cosas, pero vale la pena, en mi opini贸n. En mi opini贸n, la flexibilidad de poder almacenar de forma ordenada y segura m谩s datos del lado del cliente supera cualquier confusi贸n menor que pueda tener sobre los JWT al principio. Solo recuerde, los JWT no necesitan usarse en todas las aplicaciones, pero si el suyo tiene cierta complejidad, entonces puede beneficiarse de ellos.

    Esperamos que este art铆culo te haya ayudado a darte cuenta de que no son tan confusos como pueden parecer inicialmente. Le recomiendo encarecidamente que lea el RFC para tokens web JSON. Es sorprendentemente f谩cil de leer y proporciona mucha informaci贸n 煤til sobre el est谩ndar. Si va a utilizar esto como autorizaci贸n para las cuentas de sus usuarios, entonces vale la pena tomarse el tiempo para comprender todos los detalles detr谩s de los JWT.

    驴C贸mo ha utilizado JWT en sus aplicaciones? 驴C贸mo fue tu experiencia al usarlos? 隆H谩znoslo saber en los comentarios!

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *