Table of Contents
Implementing secure role-based access control (RBAC) is essential for modern web applications. Angular provides a robust way to manage authorization using guards, which can restrict access to routes based on user roles. This tutorial guides you through creating an Angular guard that enforces role-based permissions.
Understanding Role-Based Access Control in Angular
RBAC allows you to assign different permissions to users based on their roles, such as ‘admin’, ‘editor’, or ‘viewer’. Angular guards can check these roles before activating a route, ensuring users only access permitted areas of the application.
Setting Up User Roles and Authentication
Before implementing guards, establish a way to identify user roles. Typically, this involves:
- Authenticating users via a login system
- Storing user roles in a token or user service
- Providing a method to retrieve current user roles
For this tutorial, assume roles are stored in a JWT token and accessible through an AuthenticationService.
Creating the Role Guard
Generate a new guard using Angular CLI:
ng generate guard role
Open role.guard.ts and modify it as follows:
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class RoleGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): boolean | UrlTree | Observable | Promise {
const expectedRoles = route.data['roles'] as Array;
const userRoles = this.authService.getUserRoles();
if (this.hasRequiredRole(userRoles, expectedRoles)) {
return true;
} else {
return this.router.parseUrl('/access-denied');
}
}
private hasRequiredRole(userRoles: Array, expectedRoles: Array): boolean {
return expectedRoles.some(role => userRoles.includes(role));
}
}
Configuring Routes with Role Guards
Apply the guard to routes in your app-routing.module.ts and specify required roles:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AdminComponent } from './admin/admin.component';
import { UserComponent } from './user/user.component';
import { RoleGuard } from './role.guard';
const routes: Routes = [
{
path: 'admin',
component: AdminComponent,
canActivate: [RoleGuard],
data: { roles: ['admin'] }
},
{
path: 'user',
component: UserComponent,
canActivate: [RoleGuard],
data: { roles: ['user', 'admin'] }
},
{
path: 'access-denied',
component: AccessDeniedComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
Implementing the Authentication Service
The AuthService should provide the getUserRoles() method. Here’s a simple example:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private roles: Array = [];
constructor() {
// Example: fetch roles from token or API
this.roles = this.getRolesFromToken();
}
getUserRoles(): Array {
return this.roles;
}
private getRolesFromToken(): Array {
// Logic to decode token and extract roles
// For demonstration, return a static role
return ['user'];
}
}
Testing Role-Based Access Control
Navigate to different routes in your application. Users with appropriate roles will access protected pages, while others will be redirected to the access denied page.
This setup ensures a secure, scalable way to manage route access based on user roles in Angular applications.