Dónde guardar un JWT en una aplicación basada en navegador y cómo usarlo


Estoy tratando de implementar JWT en mi sistema de autenticación y tengo algunas preguntas. Para almacenar el token, podría usar cookies, pero también es posible usar localStorage o sessionStorage.

¿Cuál sería la mejor opción?

He leído que JWT protege el sitio de CSRF. Sin embargo, no puedo imaginar cómo funcionaría suponiendo que guarde el token JWT en el almacenamiento de cookies.

¿Cómo protegería entonces de la CSRF?

Actualización 1
Vi algunas muestras de uso como el siguiente:

curl -v -X POST -H "Authorization: Basic VE01enNFem9FZG9NRERjVEJjbXRBcWJGdTBFYTpYUU9URExINlBBOHJvUHJfSktrTHhUSTNseGNh"

¿Cómo puedo implementar eso cuando hago una solicitud al servidor desde el navegador? También vi que algunos implementan el token en la URL:

http://exmple.com?jwt=token

Si hiciera una solicitud a través de AJAX, entonces podría establecer un encabezado como jwt: [token] y luego podría leer el token desde el encabezado.

Actualización 2

Instalé la extensión avanzada del cliente REST de Google Chrome y pude pasar el token como un encabezado personalizado. ¿Es posible establecer estos datos de encabezado a través de Javascript al hacer una solicitud GET al servidor?

Author: João Angelo, 2014-10-13

3 answers

Mira este sitio web: https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token /

Si desea almacenarlos, debe usar localStorage o sessionStorage si está disponible o cookies. También debe usar el encabezado Authorization, pero en lugar del esquema Básico, use el Portador:

curl -v -X POST -H "Authorization: Bearer YOUR_JWT_HERE"

Con JS, puedes usar el siguiente código:

<script type='text/javascript'>
// define vars
var url = 'https://...';

// ajax call
$.ajax({
    url: url,
    dataType : 'jsonp',
    beforeSend : function(xhr) {
      // set header if JWT is set
      if ($window.sessionStorage.token) {
          xhr.setRequestHeader("Authorization", "Bearer " +  $window.sessionStorage.token);
      }

    },
    error : function() {
      // error handler
    },
    success: function(data) {
        // success handler
    }
});
</script>
 20
Author: Florent Morselli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-27 00:07:05

Elegir el almacenamiento es más acerca de las compensaciones que tratar de encontrar una mejor opción definitiva. Veamos algunas opciones:

Opción 1-Almacenamiento web (localStorage o sessionStorage)

Pros

  • El navegador no incluirá automáticamente nada del almacenamiento Web en las solicitudes HTTP, lo que lo hace no vulnerable a CSRF
  • Solo se puede acceder mediante Javascript que se ejecuta en el mismo dominio exacto que creó los datos
  • Permite utilizar la mayoría enfoque semánticamente correcto para pasar credenciales de autenticación de tokens en HTTP (el encabezado Authorization con un esquema Bearer)
  • Es muy fácil seleccionar las solicitudes que deben contener autenticación

Cons

  • No se puede acceder mediante Javascript que se ejecuta en un subdominio del que creó los datos (un valor escrito por example.com no se puede leer por sub.example.com)
  • ⚠️ Es vulnerable a XSS
  • Para realizar solicitudes autenticadas, solo puede use API de navegador / biblioteca que le permitan personalizar la solicitud (pase el token en el encabezado Authorization)

Uso

Aprovechar el navegador localStorage o sessionStorage API para almacenar y luego recuperar el token al realizar las solicitudes.

localStorage.setItem('token', 'asY-x34SfYPk'); // write
console.log(localStorage.getItem('token')); // read

Opción 2-Cookie de solo HTTP

Pros

  • Es no vulnerable a XSS
  • El navegador incluye automáticamente el token en cualquier solicitud que cumpla con la cookie especificación (dominio, ruta y vida útil)
  • La cookie se puede crear en un dominio de nivel superior y se puede utilizar en solicitudes realizadas por subdominios

Cons

  • }️ Es vulnerable a CSRF
  • Debe ser consciente y tener siempre en cuenta el posible uso de las cookies en los subdominios
  • Seleccionar las solicitudes que deben incluir la cookie es factible, pero messier
  • Es posible que (todavía) tenga algunos problemas con pequeñas diferencias en la forma en que los navegadores tratamiento de las cookies
  • }️ Si no tienes cuidado, puedes implementar una estrategia de mitigación de CSRF que sea vulnerable a XSS
  • El lado del servidor necesita validar una cookie para la autenticación en lugar del encabezado Authorization más apropiado

Uso

No necesita hacer nada del lado del cliente, ya que el navegador se encargará automáticamente de las cosas por usted.

Opción 3-Cookie accesible de Javascript ignorada por lado del servidor

Pros

  • Es no vulnerables a CSRF (porque es ignorado por el servidor)
  • La cookie se puede crear en un dominio de nivel superior y se puede utilizar en solicitudes realizadas por subdominios
  • Permite utilizar el enfoque semánticamente correcto para pasar credenciales de autenticación de token en HTTP (el encabezado Authorization con un esquema Bearer)
  • Es algo fácil seleccionar las solicitudes que deben contener autenticación

Cons

  • }️ Es vulnerable a XSS
  • Si no tiene cuidado con la ruta donde establece la cookie, el navegador la incluye automáticamente en las solicitudes, lo que agregará una sobrecarga innecesaria
  • Para realizar solicitudes autenticadas, solo puede usar API de navegador / biblioteca que le permitan personalizar la solicitud (pase el token en el encabezado Authorization)

Uso

Usted aprovecha la navegador document.cookie API para almacenar y luego recuperar el token al realizar solicitudes. Esta API no es tan fina como el almacenamiento web (obtienes todas las cookies), por lo que necesitas trabajo adicional para analizar la información que necesitas.

document.cookie = "token=asY-x34SfYPk"; // write
console.log(document.cookie); // read

Notas adicionales

Esto puede parecer una opción extraña, pero tiene la buena ventaja de que puede tener almacenamiento disponible para un dominio de nivel superior y todos los subdominios, que es algo que el almacenamiento web no le dará. Sin embargo, es más complejo implementar.


Conclusión-Notas finales

Mi recomendación para los escenarios más comunes sería ir con la opción 1, principalmente porque:

  • Si crea una aplicación Web, debe tratar con XSS; siempre, independientemente de dónde almacene sus tokens
  • Si no utiliza la autenticación basada en cookies, el CSRF ni siquiera debería aparecer en su radar, por lo que es una cosa menos de la que preocuparse

También tenga en cuenta que la cookie basada las opciones también son bastante diferentes, para la Opción 3 las cookies se utilizan puramente como un mecanismo de almacenamiento, por lo que es casi como si fuera un detalle de implementación del lado del cliente. Sin embargo, la opción 2 significa una forma más tradicional de tratar con la autenticación; para leer más sobre esto cookies vs token, puede encontrar este artículo interesante: Cookies vs Tokens: La Guía Definitiva.

Finalmente, ninguna de las opciones lo menciona, pero el uso de HTTPS es obligatorio, por supuesto, lo que haría significa que las cookies deben crearse adecuadamente para tener esto en cuenta.

 63
Author: João Angelo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-02 10:42:53

Esta entrada de blog tiene una excelente comparación lado a lado del almacenamiento del navegador frente a las cookies y aborda cada ataque potencial en cada caso. https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage /

La respuesta / spoiler más corto: cookies y añadir token xsrf en el jwt. Explicación detallada en la entrada del blog.

 8
Author: Carlos Arrastia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-19 07:26:07