javascript - autenticacion - Dónde guardar un JWT en una aplicación basada en navegador y cómo usarlo
autenticacion por token web api (3)
Estoy intentando 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 imaginarme cómo funcionaría suponiendo que guarde el token JWT en el almacenamiento de cookies.
¿Cómo lo protegería de CSRF?
Actualización 1
Vi algunas muestras de uso como las siguientes:
curl -v -X POST -H "Authorization: Basic VE01enNFem9FZG9NRERjVEJjbXRBcWJGdTBFYTpYUU9URExINlBBOHJvUHJfSktrTHhUSTNseGNh"
¿Cómo puedo implementar eso cuando realizo una solicitud al servidor desde el navegador? También vi que algunos implementan el token en la URL:
http://exmple.com?jwt=token
Si realizara una solicitud a través de AJAX, 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 de Google Chrome para el cliente REST avanzado y pude pasar el token como un encabezado personalizado. ¿Es posible establecer este encabezado de datos a través de Javascript al hacer una solicitud GET al servidor?
Elegir el almacenamiento se trata más de concesiones que tratar de encontrar la mejor opción definitiva. Veamos algunas opciones:
Opción 1 - Almacenamiento web (almacenamiento localStorage
o almacenamiento de localStorage
)
Pros
- El navegador no incluirá automáticamente nada desde el almacenamiento web en las solicitudes HTTP, por lo que no es vulnerable a CSRF
- Solo se puede acceder mediante JavaScript que se ejecuta en el mismo dominio exacto que creó los datos
- Permite usar el enfoque más semánticamente correcto para pasar las credenciales de autenticación de token en HTTP (el encabezado de
Authorization
con un esquema deBearer
) - Es muy fácil seleccionar las solicitudes que deben contener autenticación
Contras
- 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 porsub.example.com
) - Is️ es vulnerable a XSS
- Para realizar solicitudes autenticadas, solo puede usar las API del navegador / biblioteca que le permiten personalizar la solicitud (pase el token en el encabezado de
Authorization
)
Uso
Aproveche el navegador localStorage
o localStorage API para almacenar y luego recuperar el token cuando realice las solicitudes.
localStorage.setItem(''token'', ''asY-x34SfYPk''); // write
console.log(localStorage.getItem(''token'')); // read
Opción 2: cookie HTTP solo
Pros
- No es vulnerable a XSS
- El navegador incluye automáticamente el token en cualquier solicitud que cumpla con la especificación de cookies (dominio, ruta y duración)
- La cookie se puede crear en un dominio de nivel superior y se puede usar en solicitudes realizadas por subdominios
Contras
- It️ Es vulnerable a CSRF
- Debe tener en cuenta y siempre considerar el posible uso de las cookies en subdominios
- Cereza elegir las solicitudes que debe incluir la cookie es factible pero más desordenado
- Puede (aún) abordar algunos problemas con pequeñas diferencias en la forma en que los navegadores manejan las cookies
- ⚠️ Si no tiene cuidado, puede 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 de
Authorization
más apropiado
Uso
No necesita hacer nada del lado del cliente, ya que el navegador se encargará automáticamente de usted.
Opción 3 - Cookie accesible de JavaScript ignorada por el lado del servidor
Pros
- No es vulnerable a CSRF ( porque el servidor lo ignora )
- La cookie se puede crear en un dominio de nivel superior y se puede usar en solicitudes realizadas por subdominios
- Permite usar el enfoque más semánticamente correcto para pasar las credenciales de autenticación de token en HTTP (el encabezado de
Authorization
con un esquema deBearer
) - Es algo fácil seleccionar las solicitudes que deberían contener autenticación
Contras
- It️ Es vulnerable a XSS
- Si no tiene cuidado con la ruta donde configura la cookie, el navegador incluye automáticamente la cookie en las solicitudes que agregarán una sobrecarga innecesaria
- Para realizar solicitudes autenticadas, solo puede usar las API del navegador / biblioteca que le permiten personalizar la solicitud (pase el token en el encabezado de
Authorization
)
Uso
Aproveche la API del navegador document.cookie
para almacenar y luego recuperar el token cuando realice las solicitudes. Esta API no es tan fina como el almacenamiento web (usted obtiene todas las cookies) por lo que necesita trabajo adicional para analizar la información que necesita.
document.cookie = "token=asY-x34SfYPk"; // write
console.log(document.cookie); // read
Notas adicionales
Puede parecer una opción extraña, pero tiene la ventaja agradable de que puede tener almacenamiento disponible para un dominio de nivel superior y todos los subdominios, algo que el almacenamiento web no le brindará. Sin embargo, es más complejo de 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 donde almacene sus tokens
- Si no utiliza la autenticación basada en cookies 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 las opciones basadas en cookies también son bastante diferentes, ya que las cookies de la Opción 3 se usan exclusivamente como un mecanismo de almacenamiento, por lo que es casi como si se tratara de 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 esta cookie y token, puede encontrar este artículo interesante: Cookies vs Tokens: The Definitive Guide .
Finalmente, ninguna de las opciones lo menciona, pero el uso de HTTPS es obligatorio, por supuesto, lo que significaría que las cookies deberían crearse adecuadamente para tomar eso en consideración.
Esta publicación de blog tiene una excelente comparación paralela del almacenamiento del navegador frente a las cookies y aborda cada posible ataque 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 agregar el token xsrf en jwt. Explicación detallada en la publicación del blog.
Mire 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án disponibles o cookies. También debe usar el encabezado de Autorización, pero en lugar del esquema Básico, use el del Portador uno:
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>