Contents hide 1) Secure Routes By User Roles 2) Secure Routes Using AuthGuard Based On User Roles 3) Authorization Service (Optional) In this tutorial, we will see how Angular 10 Secure Routes Using AuthGuard Based On User Roles. Securing a route based on the token and AuthInterceptor for API is ok but also we can secure the routes based on what roles does the user has. You may have seen much application that shows an error if the user has no permission to view that page. Then let’s create that in our angular app. Secure Routes By User Roles Now let’s say we have an API that gives the currently logged-in user roles. The user role object we are maintaining also on the client-side so we can match while accessing the route. let’s say we have 4 user roles user-roles.ts export enum Roles { ADMIN = 'ADMIN', BUYER = 'BUYER', SELLER = 'SELLER', DATA_MANAGER = 'DATA MANAGER' } Now we have our users role list we can assign user roles to our individual’s routes that who has the privilege to access that page. Let’s make some change in our app-routing.module.ts app-routing.module.ts const routes: Routes = [ { path: 'onboard', loadChildren: () => import('../onboard/onboard.module').then(m => m.OnboardModule), canActivate: [AuthGuard], data: { userRoles: [] // All User Can Access but must be login } }, { path: 'dashboard', loadChildren: () => import('../dashboard/dashboard.module').then(m => m.DashboardModule), canActivate: [AuthGuard], data: { userRoles: [Roles.ADMIN, Roles.BUYER, Roles.SELLER, Roles.DATA_MANAGER] // Multiple Allowed User } }, { path: 'data-importer', loadChildren: () => import('../data-importer/data-importer.module').then(m => m.DataImporterModule), canActivate: [AuthGuard], data: { userRoles: [Roles.DATA_MANAGER] // Single Allowed User } ... ]; @NgModule({ imports: [RouterModule.forRoot(appRoutes)], exports: [RouterModule] }) export class AppRouterModule {} Now here we have set two things to secure our routes based on user roles. canActivate: [AuthGuard]: AuthGuard will contain or logic to check the assigned user role in the data object is matched with the currently logged-in user role. data: { userRoles: [Roles.DATA_MANAGER, ...] }: userRoles array will be set for the respective route which later on we can access that data in AuthGuard class. Every route can have its unique user who can access it. October 27, 2020 View Component Based on User Role In Angular 10 View Component Based on User Role User Role Service Directive To Show and Hide Based on User Roles Secure Routes Using AuthGuard Based On User Roles Now let’s jump into the auth guard implementation which will contain the method which route can be accessed by validating user role. app/core/auth.guard.ts import { Injectable, Inject } from '@angular/core'; import { Router, CanActivate, CanActivateChild, CanLoad, ActivatedRouteSnapshot} from '@angular/router'; import { Roles } from './util/user-roles'; import { AuthorizationService } from './authorization.service'; @Injectable() export class AuthGuard implements CanActivate, CanActivateChild, CanLoad { constructor( @Inject(AuthorizationService) private authorizationService: AuthorizationService, @Inject(Router) private router: Router ) {} /** * Can this route be activated? * @param {ActivatedRouteSnapshot} route - The route. * @returns {Promise<boolean>} True if user is authenticated otherwise false */ public async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> { const allowedUserRoles = this.getRoutePermissions(route); return await this.checkPermission(allowedUserRoles); } /** * Can this child route be activated? * @param {ActivatedRouteSnapshot} route - The route. * @returns {Promise<boolean>} True if user is authenticated otherwise false */ public async canActivateChild(route: ActivatedRouteSnapshot): Promise<boolean> { const allowedUserRoles = this.getRoutePermissions(route); return await this.checkPermission(allowedUserRoles); } /** * Can this route be loaded. * @returns {Promise<boolean>} True if user is authenticated otherwise false */ public canLoad(): Promise<boolean> { return this.checkPermission(null); } /** * Get allowed user roles from the route. * @param {ActivatedRouteSnapshot} route - The route. * @returns {string[]} All user roles that are allowed to access the route. */ private getRoutePermissions(route: ActivatedRouteSnapshot): Roles[] { if (route.data && route.data.userRoles) { return route.data.userRoles as Roles[]; } return null; } /** * Check if a user is authenticated * @param {string[]} allowedUserRoles - These user roles have the permissions to access the route. * @returns {Promise<boolean>} True if user is authenticated otherwise false */ private checkPermission(allowedUserRoles: Roles[]): Promise<boolean> { return this.authorizationService.getSession().then((session: boolean) => { if (session) { if (!allowedUserRoles) { return true; // if no user roles has been set, all user are allowed to access the route } else { return this.authorizationService.getUserRoles().then((userRoles: string[]) => { if (this.authorizationService.areUserRolesAllowed(userRoles, allowedUserRoles)) { return true; } else { this.router.navigateByUrl('/nopermission'); return false; } }); } } else { return false; } }); } } The three main functions of the angular router are CanActivate, CanActivateChild, CanLoad. With these methods, we can manage our authentication for routes. These methods will have a return type boolean i.e. whether to load or not. other than that we have our private custom method getRoutePermissions which will give us the route data from ActivatedRouteSnapshot and the checkPermission method is linked with another service that will validate both the token-based session and also it will get the user-role from the server. Authorization Service (Optional) We have understood the AuthGuard, but you might have a question in mind about what was in the authorization service? The three methods of authorization service which I used in AuthGuard are as below. getSession() public getSession(): Promise<boolean> { const session = localStorage.getItem('token'); return new Promise((resolve, reject) => { if (session) { return resolve(true); } else { return reject(false); } }); } we have checked whether the token is set after login or not. You must use the JWT token to or someone hacks your system by manually putting value in local storage. getUserRoles() public getUserRoless(): Promise<string[]> { return new Promise((resolve, reject) => { this.http.get(`${this.baseUrl}getUserRoles`) .pipe(catchError((error: any, caught: any) => { reject(error); return caught; }), map((res: any) => res.data)) .subscribe((role: string[]) => { resolve(role); }); }); } In this method, we are just fetching the logged-in user roles list. Note: As on every route change, this will call an API that can make a huge load on the server, instead of that we can use the cache data by maintaining a response object, or we can cache the API response. Learn More About it: How can we cache the HTTP requests in Angular 10? areUserRolesAllowed() public areUserRolesAllowed(userRoles: string[], allowedUserRoles: Roles[]): boolean { for (const role of userRoles) { for (const allowedRole of allowedUserRoles) { if (role.toLowerCase() === allowedRole.toLowerCase()) { return true; } } } return false; } this method will only iterate data from both arrays and checks its include or not. Get More tutorials on Angular 10 Share this:TwitterFacebookRedditLinkedInWhatsAppPrintTumblr Related Tags: Angular 10, Angular Router, AuthGuard