In any back-end application, security of routes plays an essential part in providing permission to authorized users to access resources. Nest.js, which is a progressive Node.js framework, offers Guards as a standard module for processing authentication and authorization.
The security system of Nest.js utilizes specific implementation methods that work as middleware pieces. Guards indicate which requests should proceed through particular condition-based examinations. Guards at the route level function before the route handler to perform their operations.
The main use of guards occurs during authentication processes to determine if users have already logged in so they can access protected routes.
Let’s go step by step to implement a basic authentication guard in a Nest.js application.
1. Create a Custom Guard
Nest.js provides an interface called CanActivate, which must be implemented when creating a guard.
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { Request } from 'express';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
canActivate(context: ExecutionContext): boolean {
const request: Request = context.switchToHttp().getRequest();
const authHeader = request.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
throw new UnauthorizedException('Missing or invalid token');
}
const token = authHeader.split(' ')[1];
try {
const decoded = this.jwtService.verify(token);
request.user = decoded; // Attaching the decoded user data to the request object
return true;
} catch (error) {
throw new UnauthorizedException('Invalid token');
}
}
}
Guards can be applied at different levels:
At the Controller Level
Applying a guard to an entire controller ensures all routes inside it are protected.
import { Controller, Get, UseGuards } from '@nestjs/common';
@Controller('protected')
@UseGuards(AuthGuard)
export class ProtectedController {
@Get()
getData() {
return { message: 'This is a protected route' };
}
}
At the Route Level
If you want to protect only specific routes, apply the guard to the method:
import { Controller, Get, UseGuards } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Get('profile')
@UseGuards(AuthGuard)
getProfile() {
return { message: 'User profile data' };
}
}
If you need to apply an authentication guard across all routes in your application, you can register it globally in the main AppModule:
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
@Module({
providers: [
{
provide: APP_GUARD,
useClass: AuthGuard,
},
],
})
export class AppModule {}
This ensures that every request is checked before reaching any controller.
Beyond authentication, guards can be used for role-based authorization, ensuring only users with specific roles can access certain resources.
Let’s create a RolesGuard to allow only users with a specific role (e.g., admin):
import { CanActivate, ExecutionContext, Injectable, ForbiddenException } from '@nestjs/common';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private allowedRoles: string[]) {}
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const user = request.user; // Assuming the AuthGuard has set the user object
if (!user || !this.allowedRoles.includes(user.role)) {
throw new ForbiddenException('You do not have permission to access this resource');
}
return true;
}
}
To use this guard dynamically, create a decorator:
import { SetMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
Apply it to specific routes:
import { Controller, Get, UseGuards } from '@nestjs/common';
import { RolesGuard } from './roles.guard';
import { Roles } from './roles.decorator';
@Controller('admin')
export class AdminController {
@Get()
@UseGuards(new RolesGuard(['admin'])) // Only admins can access this route
getAdminData() {
return { message: 'Admin panel data' };
}
}
Nest.js Guards provide a powerful way to secure routes by handling authentication and authorization before requests reach the controller.
Custom Guards can be implemented using the CanActivate interface to verify user credentials.
Flexible Usage allows guards to be applied at the route, controller, or global level based on security needs.
Role-Based Access Control (RBAC) can be enforced using guards to restrict access based on user roles.
Global Guards can be set up to ensure that every request is authenticated without manually applying guards to each route.
This approach helps maintain a secure, modular, and scalable Nest.js application.
Ready to transform your business with our technology solutions? Contact us today to Leverage Our Nodejs Expertise.