Route Guards Based on Permission in Angular (Enterprise)

Route Guards Based on Permission in Angular (Enterprise)

This setup includes:

  • ✔ Prevent user from opening URL directly
  • ✔ Redirect to 403 Forbidden page
  • ✔ Supports roles + permissions
  • ✔ Works with lazy loaded modules

1️⃣ Create Forbidden Component (403 Page)


// forbidden.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-forbidden',
  template: `
    

403 - Forbidden

You don’t have permission to access this page.

` }) export class ForbiddenComponent {}

2️⃣ Add Route Data (Permission Required)


// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ForbiddenComponent } from './forbidden.component';
import { PermissionGuard } from './core/auth/permission.guard';

const routes: Routes = [
  {
    path: 'dashboard',
    canActivate: [PermissionGuard],
    data: { permissions: ['DASHBOARD_VIEW'] },
    loadComponent: () => import('./pages/dashboard/dashboard.component').then(m => m.DashboardComponent)
  },
  {
    path: 'users',
    canActivate: [PermissionGuard],
    data: { permissions: ['USERS_VIEW'] },
    loadChildren: () => import('./pages/users/users.module').then(m => m.UsersModule)
  },
  { path: 'forbidden', component: ForbiddenComponent },
  { path: '**', redirectTo: 'dashboard' }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

3️⃣ Permission Guard (Enterprise)


// permission.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, Router } from '@angular/router';
import { PermissionService } from './permission.service';
import { Permission } from './permission.model';

@Injectable({ providedIn: 'root' })
export class PermissionGuard implements CanActivate {

  constructor(
    private permissionService: PermissionService,
    private router: Router
  ) {}

  canActivate(route: ActivatedRouteSnapshot): boolean {
    const requiredPermissions = route.data['permissions'] as Permission[];

    // if no permission required, allow
    if (!requiredPermissions || requiredPermissions.length === 0) {
      return true;
    }

    const allowed = this.permissionService.hasAnyPermission(requiredPermissions);

    if (!allowed) {
      this.router.navigate(['/forbidden']);
      return false;
    }

    return true;
  }
}

4️⃣ Secure Child Routes also (Best Practice)

For nested routes, use canActivateChild:


// permission.guard.ts (upgrade)
import { CanActivateChild } from '@angular/router';

export class PermissionGuard implements CanActivate, CanActivateChild {

  canActivateChild(route: ActivatedRouteSnapshot): boolean {
    return this.canActivate(route);
  }
}

// Usage in routing
{
  path: 'users',
  canActivateChild: [PermissionGuard],
  data: { permissions: ['USERS_VIEW'] },
  children: [
    // child routes here
  ]
}

5️⃣ Lazy Loaded Module Protection


// users-routing.module.ts
const routes: Routes = [
  {
    path: '',
    canActivate: [PermissionGuard],
    data: { permissions: ['USERS_VIEW'] },
    component: UsersListComponent
  },
  {
    path: 'create',
    canActivate: [PermissionGuard],
    data: { permissions: ['USERS_CREATE'] },
    component: UsersCreateComponent
  }
];

🔥 Interview Explanation (Perfect)

Q) How do you stop user from accessing URL directly?

  • ✅ I use a Route Guard and check required permissions from route.data.
  • ✅ If permission is missing, I redirect to /forbidden.

Q) Why still need guard if menu is hidden?

  • ✅ Hiding menu is only UI security.
  • ✅ Guard ensures frontend route-level protection similar to backend authorization.

Comments

Popular posts from this blog

Debouncing & Throttling in RxJS: Optimizing API Calls and User Interactions

Promises in Angular

Comprehensive Guide to C# and .NET Core OOP Concepts and Language Features