Autenticación en Angular: Uso de guardias de ruta

Autenticación en Angular: Uso de guardias de ruta

¿Qué son los guardias de ruta?

Los guardias de ruta de Angular son interfaces que pueden indicar al enrutador si debe o no permitir la navegación a una ruta solicitada. Toman esta decisión buscando un valor de retorno true o false de una clase que implemente la interfaz de guardia dada.


Hay cinco tipos diferentes de guardias y cada una de ellas se llama en una secuencia particular. El comportamiento del router se modifica de forma diferente dependiendo de la guardia que se utilice.


Las guardias son:


  • CanActivate
  • CanActivateChild
  • CanDeactivate
  • CanLoad
  • Resolve
  • AuthService

No vamos a entrar demasiado en los detalles de cada guardia aquí, pero puedes ver los documentos de Angular para más información.


Decisiones de enrutamiento basadas en la caducidad de los tokens

Si estás usando JSON Web Tokens (JWT) para asegurar tu aplicación Angular (y te recomiendo que lo hagas), una forma de tomar una decisión sobre si se debe acceder a una ruta o no es comprobar el tiempo de expiración del token. Es probable que estés usando el JWT para permitir a tus usuarios acceder a recursos protegidos en tu backend. Si este es el caso, el token no será útil si está caducado, por lo que es una buena indicación de que el usuario debe ser considerado "no autenticado".


Crea un método en tu servicio de autenticación que compruebe si el usuario está autenticado o no. De nuevo, para los propósitos de la autenticación sin estado con JWT, esto es simplemente una cuestión de si el token ha expirado. El JwtHelperService class from angular2-jwt puede utilizarse para ello.


Utilice angular-jwt en su AuthService


NOTA: Este ejemplo asume que usted está almacenando el JWT del usuario en el almacenamiento local.


Crea un nuevo servicio que implemente la guardia de ruta. Puedes llamarlo como quieras, pero algo como auth-guard.service suele ser suficiente.


El servicio inyecta AuthService y Router y tiene un único método llamado canActivate. Este método es necesario para aplicar correctamente la interfaz CanActivate.


El método canActivate devuelve un boolean que indica si se debe permitir o no la navegación a una ruta.Si el usuario no está autenticado, es redirigido a algún otro lugar, en este caso una ruta llamada /login.


Ahora el protector puede aplicarse a cualquier ruta que desee proteger.


La ruta /profile tiene ahora un valor de configuración extra: canActivate. El AuthGuard que se creó anteriormente se pasa a un array para canActivate, lo que significa que se ejecutará cada vez que alguien intente acceder a la ruta /profile. Si el usuario está autenticado, llega a la ruta. Si no, son redirigidos a la ruta /login.


Nota: La guarda canActivate sigue permitiendo que se active el componente de una ruta determinada (pero no que se navegue hacia él). Si quisiéramos evitar la activación por completo, podríamos utilizar la guarda canLoad.


Comprobación de la función de un usuario

El ejemplo anterior funciona bien para escenarios que son bastante sencillos. Si un usuario está autenticado, déjalo pasar. Sin embargo, hay muchos casos en los que querremos ser un poco más precisos con nuestras decisiones de enrutamiento.


Por ejemplo, puede que queramos permitir el acceso a una ruta sólo a los usuarios que tengan un determinado rol asociado a su cuenta. Para manejar estos casos podemos modificar el guardián para buscar un determinado rol en la carga útil del JWT del usuario.


Instala jwt-decode para que podamos leer la carga útil del JWT.


Dado que habrá ocasiones en las que queramos utilizar tanto el AuthGuard general como un guardián basado en roles más detallado, vamos a crear un nuevo servicio para poder manejar ambos casos.


Crea un nuevo servicio de guardia llamado RoleGuardService.


En esta guardia estamos usando ActivatedRouteSnapshot para darnos acceso a la propiedad data de una ruta determinada. Esta propiedad de datos es útil porque podemos pasarle un objeto con algunas propiedades personalizadas desde la configuración de nuestra ruta. Luego podemos recoger esos datos personalizados en la guardia para ayudar a tomar decisiones de enrutamiento.


En este caso estamos buscando un rol que esperamos que el usuario tenga si se le permite el acceso a la ruta. A continuación, decodificamos el token para obtener su carga útil. Si el usuario no está autenticado o si no tiene el rol que esperamos que tenga en la carga útil del token, cancelamos la navegación y hacemos que se registre. De lo contrario, son libres de proceder.


Ahora podemos usar este RoleGuardService para cualquiera de nuestras rutas. Podemos, por ejemplo, querer proteger una ruta /admin.


Para la ruta /admin, seguimos usando canActivate para controlar la navegación, pero esta vez pasamos un objeto en la propiedad data que tiene esa clave expectedRole que ya hemos visto en el RoleGuardService.


NOTA: Este escenario asume que usted está usando un reclamo de rol personalizado en su JWT.


¿No es esto fácilmente hackeable? 

Si eres como la mayoría de los desarrolladores, probablemente estés viendo esto y pensando que el usuario podría hackear muy fácilmente su camino hacia una ruta protegida. Después de todo, cualquier usuario con conocimientos podría encontrar su JWT en el almacenamiento local, dirigirse a jwt.io, conectar el token y cambiar su carga útil. Por ejemplo, podrían cambiar la exp en un intento de extender la vida del token, o podrían darse a sí mismos un role diferente.


Todo esto es cierto: un usuario podría hacer esto y pasar los guardias. Sin embargo, el punto clave que hay que recordar es que cualquier cambio que el usuario haga en la carga útil de su token invalidará la firma. Las firmas de los tokens JSON Web se calculan incluyendo la carga útil, por lo que cualquier modificación de la misma invalidará todo el proceso. Esto es una buena noticia porque significa que el usuario no podrá acceder a sus recursos protegidos con él.


Cualquier dato sensible al que no quieras que accedan personas no autorizadas debe mantenerse detrás de tu servidor. Si el usuario se las arregla para llegar a una ruta que se supone que no debe, de todos modos no importa mucho, porque no podrá ver ningún dato que la ruta proporcione normalmente.


Pero quiero bloquear las rutas por completo 

En algunos casos, todavía hay un fuerte deseo de bloquear las rutas del lado del cliente por completo. Aunque no es posible tener una protección del 100% de cualquier cosa en el lado del cliente, Angular proporciona algunas posibilidades interesantes a través del enrutamiento asíncrono. Veremos cómo podemos utilizar el enrutamiento asíncrono a nuestro favor en un futuro post.


Para terminar

Esperamos que hayas podido ver los beneficios de usar los guardias de ruta de Angular para ayudar a proteger el acceso a las rutas del lado del cliente. Recuerda que nada en el cliente puede estar realmente protegido. Cualquier código, datos u otros activos que se entregan al navegador del usuario son accesibles por ellos. Sabiendo esto, asegúrate de proteger siempre los datos sensibles en tu backend.


Reactions

7

0

0

0

Access hereTo be able to comment

TheWhiteCode.com is not the creator or owner of the images shown, references are: