Logo Studenta

Clase 22 - Passport Avanzado

¡Estudia con miles de materiales!

Vista previa del material en texto

Clase 22. Passport Avanzado 
Formas de envío de JWT
Envío desde headers de autorización
Una de las formas en las cuales se puede trabajar con JWT es apoyándonos del local storage. Este es un recurso que almacena información en una “base interna” del navegador. Así, este podrá acceder al recurso guardado desde cualquier vista. 
¿Cómo conecta esto con nosotros?
Cuando el cliente hace alguna consulta al servidor, este envía desde sus headers un header “Authorization”, donde se enviará el token guardado, precedido por la palabra “Bearer”.
Un ejemplo de un token enviado sería
Authorization : “Bearer asLKcU132zccllfxzl34”
1. El cliente envía la petición de login como lo hemos visto en clases pasadas
2. Nota que el token generado es enviado en el json de respuesta.
3. El cliente recibirá el token desde la respuesta y lo almacenará en localstorage. Es decir, de manera interna en el navegador. 
4. La próxima vez que el cliente quiera hacer una petición, enviará en sus headers un nuevo campo de Authorization, el cual contendrá el token previamente almacenado.
Vulnerabilidad en localstorage
Localstorage no es del todo seguro
Pasa que el utilizar jwt con localstorage puede prestarse a ataques maliciosos, donde el más importante a considerar es un ataque de tipo XSS ( Cross Site Scripting ), donde se puede inyectar scripting malicioso a la información, con el fin de tomar la información que se considere necesaria. 
Una solución a esto suele ser el crear una conexión entre nuestro front y nuestro back a partir de un header personalizado.
Sin embargo, podemos evitar esta configuración adicional de headers si optamos por guardar nuestro jwt desde una cookie para el cliente.
Enviar token desde cookie
El proceso es muy similar a lo visto anteriormente: 
· El cliente enviará sus credenciales para su proceso de autenticación
· Esta vez, en lugar de enviar el token directamente en nuestro res.send(), se colocará el token en una cookie para almacenarse en el lado del cliente. 
¡Pero falta algo!
Aún con jwt en la cookie recién vista, es importante recordar que, de lado del frontend, las cookies pueden ser fácilmente accedidas a partir de document.cookie. ¿No es, entonces, una forma sencilla de acceder a la información que queremos? 
Por ello, no permitiremos que nuestra cookie pueda ser accedida por medio de código ajeno a una petición. Se configura entonces la cookie para que sólo exista en el proceso de la petición HTTP
Estrategia de JWT con passport
Configurar el servidor a trabajar
A estas alturas, ya conocemos passport y cómo funciona una configuración passport habitual, vamos a aplicar una nueva estrategia para nuestro passport, con el fin de que esta pueda trabajar con jwt
La estrategia de jwt permitirá obtener el token, descifrarlo, verificarlo y parsearlo en el usuario que corresponda a ese token. 
Ya tenemos instalado jwt en este momento, así que solo nos falta instalar passport y passport-jwt como se indica.
Comenzamos con el cuerpo inicial de passport.Nota que declaremos la estrategia que vamos a utilizar. 
Nociones importantes
· Entendiendo que jwt se puede obtener de los headers, del body mismo, o bien de una cookie, necesitaremos el estilo de “extracción de token” que vayamos a utilizar.
· Passport no controla las cookies por sí solo. ocupará una función personalizada por nosotros para extraer la cookie, a lo cual llamaremos cookieExtractor.
· Ya que el módulo session es quien controlaba las cookies y ahora no lo utilizamos, tendremos que volver a utilizar el middleware de cookieParser. (Ten claro el ) y configurar el middleware en app.js
· Si se configura correctamente la estrategia, passport contendrá el usuario ya parseado a partir de un campo jwt_payload.
Cuerpo de una estrategia de JWT para passport
El cookieExtractor que se utiliza en la captura anterior. 
Puedes colocar esta función en el mismo archivo donde estás realizando la configuración de tu estrategia.
Por último, los middlewares
Ahora, en app.js colocamos la inicialización de nuestro passport, la inicialización de passport y cookieParser también para que el servidor pueda reconocer correctamente las cookies. 
Middlewares en app.js
Control interno de mensajes y sistema de roles con passport
¿Cómo gestionar un error en passport?
En muchas ocasiones necesitamos obtener información más específica sobre la información que estamos tratando de obtener. Un status 401 significa unauthorized, mas no sabemos realmente por qué está ocurriendo dicho error. 
Por ejemplo, esto es lo que obtengo si corremos nuestra estrategia de jwt en la ruta “/current” sin haber enviado un token. obtenemos esto:
Y vale, me queda claro que no estoy autorizado, pero ¿por qué?, ¿El front no lo envió? ¿El token está corrupto? ¿Expiró? ¿Qué pasa?
Ahora, supongamos que el cliente manda un jwt que ha sido alterado o está corrupto, el mensaje que obtendremos es el siguiente:
¡Importante!
¡Nota que no hay diferencia! Cuando desarrollamos, es crucial tener un registro claro de la razón del error, por lo que necesitamos encontrar una forma de saber las razones por las cuales ocurre dicho código 401.
Creando un custom passportCall
Crearemos, en un archivo utils.js, una función que utilice la función authenticate de passport, sin embargo, configuraremos la función raíz para poder controlar los errores, el usuario, pero sobre todo, los mensajes de información.
¿Cómo utilizar passportCall?
Ya que nuestra Custom Call manda a llamar de manera interna, podemos intuir que al final podemos utilizarlo como un middleware más, por lo que, al momento de mandar a llamar el endpoint donde queremos que se utilice, solo lo mandamos a llamar, con el nombre de la estrategia de mi interés:
Volvamos a hacer pruebas
Mandar a llamar a “current” SIN TOKEN
Mandando a llamar a “current” con un token alterado o corrupto.
¡Mucho mejor!
Ahora es mucho más fácil visualizar errores, warnings, o información en general de lo que necesite enviar durante mis estrategias de passport.
Por ejemplo, si quisiéramos indicar que hay un error por “User not found”, tendríamos que enviar el mismo callback (done, false), pero añadiendo un argumento nuevo con la información que nos interesa:
¡Maravilloso! Ahora podemos mantener un informe más transparente de lo que sucede durante el proceso de cada una de nuestras estrategias.
Middleware de autorización mezclado con Passport
Creando el middleware de autorización 
Primero, comenzamos con el middleware elemental de autorización para corroborar si el usuario es “user” o “admin”.
Conectando middlewares
Una vez que passport nos devuelva al usuario, será mucho más sencillo colocar como middleware siguiente, el middleware de autorización que acabamos de hacer:
Para probar esto, modificaremos nuestro login del inicio, para darle un rol a nuestro usuario hardcodeado.
En caso de que el rol se cumpla en el middleware, el resultado será:
Sin embargo, en caso de colocar algún valor diferente al middleware de autorización, el resultado será: 
¡Importante!
Los middlewares van paso a paso. Hay que tener cuidado referente al orden en el que mandamos a llamar cada middleware. Si colocamos la autorización antes que el call de passport, no habrá un req.user del cual apoyarse, y te podría causar errores lógicos.

Continuar navegando

Materiales relacionados