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
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);
}
}
- For now using mock roles and permissions which normally is retrieved from a backend -
rolePermissions - Here we are doing simple
loginmethod 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;
}
}
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)],
};
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);
}
}
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>
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();
}
}
dashboard.component.html
<h2>Dashboard</h2>
<p>Hey</p>
<p>Your Permissions:</p>
<ul>
<li *ngFor="let permission of permissions">{{ permission }}</li>
</ul>
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 {}
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)