How to use role in authguard to protect routes?

Viewed 54

I have a application and i'm checking for authorisation to protecting route using AuthGuard. Now i want to protect my child routes with autguard based on role system which i'm getting response from backend while logging in. If role is admin i will allow him to view all routes. If role is user i want him to access only notification route. I tried using *ngIf but i will hide only route, but when user enter URL it will be redirecting

auth.guard.ts

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

    const isAuth = this.authService.getIsAuth();
    if (!isAuth) {
      this.router.navigate(['/sign-in']);
    }
    return isAuth;
  }

roleAuth.guard.ts

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

    const role = this.authService.role();
    if (role ==='Admin') {
     //got  stuck here
    }
   if (role ==='moderator') {
     //got  stuck here
    }
   if (role ==='user') {
     //got  stuck here
    }
    return role;
  }

app-routing.ts

const routes: Routes = [
  { path: 'sign-in', component: SignInComponent },
  {
    path: '',
    canActivate: [AuthGuard],
    component: SideNavComponent,
    children: [
      { path: '', redirectTo: '/dashboard', pathMatch: 'full' },

      {
        path: 'dashboard',
        loadChildren: () => import('./components/sidenav/pages/dashboard/dashboard.module')
          .then(m => m.DashboardModule)
      },
      {
        path: 'notifications',
        loadChildren: () => import('./components/sidenav/pages/notifications/notifications.module')
          .then(m => m.NotificationsModule)
      },

    ],
  },

];
2 Answers

You need to have a RoleAdminGuard and use canActivate / canLoad for dashboard route. Something like this

role-admin.guard.ts

canLoad(route: Route, segments: UrlSegment[]): Observable<boolean>|Promise<boolean>|boolean {
    const isAdmin = this.authService.getAuth().role === 'ADMIN';
    if (isAdmin) {
      this.router.navigate(['/notifications']);
    }
    return isAdmin;
}

app-routing.module.ts

const routes: Routes = [
  { path: 'sign-in', component: SignInComponent },
  {
    path: '',
    canActivate: [AuthGuard],
    component: SideNavComponent,
    children: [
      { path: '', redirectTo: '/dashboard', pathMatch: 'full' },

      {
        path: 'dashboard',
        canLoad: [RoleAdminGuard],
        loadChildren: () => import('./components/sidenav/pages/dashboard/dashboard.module')
          .then(m => m.DashboardModule)
      },
      {
        path: 'notifications',
        loadChildren: () => import('./components/sidenav/pages/notifications/notifications.module')
          .then(m => m.NotificationsModule)
      },

    ],
  },

];

In your scenario i guess you have to apply child level route restrictions, In order to do that you have to split your project in to feature module architecture Angular Guide for feature module. once you do this change you can simply apply your [Authguard] on to child routes in side your feature module routing.

const routes: Routes = [
    {
        path: '',
        component: ClientDashboardComponent
    },
    {
        path: 'edit/:id',
        component: ClientEditComponent,
        canActivateChild: [AuthorizeGuard],
        data: { roles: [PermissionCodes.ClientProfile_Write] },
        canDeactivate: [CanDeactivateGuard]
    } ]

just like this you can restrict your child route even you enter url in new tab. hope this will help for you

Related