DEV Community

Cover image for Permission Based Authorization in Angular (PBAC)
Arpan Sarkar
Arpan Sarkar

Posted on

Permission Based Authorization in Angular (PBAC)

Authorization is a critical part of any Angular application, ensuring that users can only access the parts of the application they are permitted to.
In most applications, users have assigned roles.
We can enforce access control in Angular routes by using route guards.

In many applications, role based access control (RBAC) alone is not enough. Users may need fine grained permissions beyond just roles. For example:

Admin - Can manage users and edit settings.
Editor - Can edit articles but not manage users.
Viewer - Can only view content.

In this article, we’ll see how in Angular to include

  • Permission Based access control (PBAC)

Step 1: Setting Up the Angular Application

Start by creating a new Angular app if you don’t have one

ng new angular-pbac --routing
Enter fullscreen mode Exit fullscreen mode

Step 2: Create an Auth Service for Dynamic Permissions

This service will store user roles with associated permissions, retrieve them dynamically from an API (mocked for now) and provide authentication authorization methods.

auth.service.ts

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';

@Injectable({
  providedIn: 'root',
})
export class AuthService {
  private user: { role: string; permissions: string[] } | null = null;

  private rolePermissions: Record<string, string[]> = {
    admin: ['manage-users', 'edit-settings', 'view-dashboard'],
    editor: ['edit-articles', 'view-dashboard'],
    viewer: ['view-dashboard'],
  };

  constructor(private router: Router) {}

  login(role: string): void {
    const permissions = this.rolePermissions[role] || [];
    this.user = { role, permissions };
    localStorage.setItem('userPermissions', JSON.stringify(permissions));
    this.router.navigate(['/dashboard']);
  }

  logout(): void {
    this.user = null;
    localStorage.removeItem('userPermissions');
    this.router.navigate(['/login']);
  }

  getUserPermissions(): string[] {
    return JSON.parse(localStorage.getItem('userPermissions') || '[]');
  }

  hasPermission(permission: string): boolean {
    return this.getUserPermissions().includes(permission);
  }
}
Enter fullscreen mode Exit fullscreen mode
  • For now using mock roles and permissions which normally is retrieved from a backend - rolePermissions
  • Here we are doing simple login method without setting user role or checking if authenticated or not. Just to keep it simple we are avoiding that

Step 3: Create a Permission Based Route Guard

In Angular, Route guards help protect routes based on authentication and roles.
Now, we need a route guard to check for both roles and permissions before allowing access.

permission.guard.ts

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, Router } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable({
  providedIn: 'root',
})
export class PermissionGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot): boolean {
    const requiredPermission = route.data['permission'];

    if (!this.authService.hasPermission(requiredPermission)) {
      this.router.navigate(['/unauthorized']);
      return false;
    }

    return true;
  }
}

Enter fullscreen mode Exit fullscreen mode

Step 4: Define Routes with Permission Based Access

Now, we will apply our new permission-based guard to specific routes.

app.config.ts

import { provideRouter, Route } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { UnauthorizedComponent } from './unauthorized/unauthorized.component';
import { PermissionGuard } from './permission.guard';


const routes: Routes = [
  { path: 'login', component: LoginComponent },
  { path: 'dashboard', component: DashboardComponent },

  // Permission based routes 
  { path: 'edit-settings', component: DashboardComponent, canActivate: [PermissionGuard], data: { permission: 'edit-settings' } },
  { path: 'manage-users', component: DashboardComponent, canActivate: [PermissionGuard], data: { permission: 'manage-users' } },

  { path: 'unauthorized', component: UnauthorizedComponent },
  { path: '', redirectTo: '/login', pathMatch: 'full' },
];

export const appConfig = {
  providers: [provideRouter(routes)],
};

Enter fullscreen mode Exit fullscreen mode

Step 5: Setup Login Component to Handle Dynamic Roles

Now, users can log in as different roles dynamically, and permissions will be applied accordingly.

login.component.ts

import { Component } from '@angular/core';
import { AuthService } from '../auth.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html'
})
export class LoginComponent {
  constructor(private authService: AuthService) {}

  loginAs(role: string) {
    this.authService.login(role);
  }
}
Enter fullscreen mode Exit fullscreen mode

login.component.html

<h2>Login</h2>
<button (click)="loginAs('admin')">Login as Admin</button>
<button (click)="loginAs('editor')">Login as Editor</button>
<button (click)="loginAs('viewer')">Login as Viewer</button>

Enter fullscreen mode Exit fullscreen mode

Step 6: Display logged in user Permissions in Dashboard

Now, let’s display permissions dynamically on the dashboard.

dashboard.component.ts

import { Component } from '@angular/core';
import { AuthService } from '../auth.service';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
})
export class DashboardComponent {
  permissions: string[];

  constructor(private authService: AuthService) {
    this.permissions = this.authService.getUserPermissions();
  }
}

Enter fullscreen mode Exit fullscreen mode

dashboard.component.html

<h2>Dashboard</h2>
<p>Hey</p>
<p>Your Permissions:</p>
<ul>
  <li *ngFor="let permission of permissions">{{ permission }}</li>
</ul>

Enter fullscreen mode Exit fullscreen mode

Step 7: Handling Unauthorized Access

If a user lacks permissions, they will be redirected to an Unauthorized Page.

unauthorized.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-unauthorized',
  template: '<h2>Unauthorized Access</h2>',
})
export class UnauthorizedComponent {}

Enter fullscreen mode Exit fullscreen mode

Conclusion: Building a Fortress of Access Control

In this guide, We seen Angular authorization system by:
✅ Implementing dynamic permissions.
✅ Protecting routes based user permissions.
✅ Automatically handling unauthorized access with redirection.

Authorization in Angular is not just about opening and closing doors - it is about building a fortress with layers of security. Roles and Permissions define the broad gates users can pass through, while permissions act as the keys unlocking specific chambers within. By implementing permission based access control (PBAC), we create a system that is both scalable and adaptive, which ensures users only access they need.

As your application grows, this structured approach will become your architectural blueprint, guiding security while maintaining flexibility.

Did you learn something new today? Let me know in the comments below! 👇

Top comments (0)