Authorization is a vital part of any web application, ensuring that users can only access resources and endpoints they are allowed to. In NestJS, this is typically handled using Guards. In this article, we will dive into the mechanics of Guards, how to create them, and how to use them to secure your routes and implement authorization in your NestJS applications.
In NestJS, Guards are a powerful way to implement authorization logic. They can be used to determine if a request should be processed further based on specific conditions. Essentially, a Guard is a class that implements the CanActivate
interface, which has a method canActivate
that returns a boolean value (or a Promise that resolves to a boolean).
Here's a basic overview of the CanActivate
interface:
import { CanActivate, ExecutionContext } from '@nestjs/common'; export interface CanActivate { canActivate(context: ExecutionContext): boolean | Promise<boolean>; }
Let’s start by creating a simple guard that checks if a user is authenticated. First, ensure that you have NestJS set up, and then follow these steps:
Using the Nest CLI, you can generate a new guard by running:
nest g guard auth
This will create a new guard file in your project, generally in the src
directory.
Open the generated auth.guard.ts
file and implement the canActivate
method. For demonstration purposes, this guard will check for a user object in the request, assuming authentication has been performed and set a user in the request.
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; @Injectable() export class AuthGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest(); return request.user ? true : false; // Checks if user is authenticated } }
Now that you've created your guard, you need to apply it to your routes. You can apply guards at the controller level or the route handler level.
Here’s how to apply it to the entire controller:
import { Controller, Get, UseGuards } from '@nestjs/common'; import { AuthGuard } from './auth.guard'; @Controller('protected') @UseGuards(AuthGuard) export class ProtectedController { @Get() getProtectedResource() { return { message: 'This is a protected resource!' }; } }
Or, if you want to protect just a single route, you can do it like this:
import { Controller, Get, UseGuards } from '@nestjs/common'; import { AuthGuard } from './auth.guard'; @Controller('public') export class PublicController { @Get('protected') @UseGuards(AuthGuard) getProtectedResource() { return { message: 'This is a protected resource!' }; } }
Besides simple authentication, you might want to implement roles-based authorization to control access based on user roles. Let’s extend our guard to incorporate role checking.
Create a new guard file using the Nest CLI:
nest g guard roles
In the generated roles.guard.ts
, implement a guard that checks the roles:
import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common'; @Injectable() export class RolesGuard implements CanActivate { constructor(private readonly roles: string[]) {} canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest(); const user = request.user; if (!user || !user.roles) { throw new ForbiddenException('You do not have permission to access this resource.'); } const hasRole = () => user.roles.some(role => this.roles.includes(role)); if (!hasRole()) { throw new ForbiddenException('You do not have permission to access this resource.'); } return true; } }
You would apply the RolesGuard
similarly:
import { Controller, Get, UseGuards } from '@nestjs/common'; import { RolesGuard } from './roles.guard'; import { SetMetadata } from '@nestjs/common'; @Controller('admin') @UseGuards(RolesGuard) export class AdminController { @Get('dashboard') @SetMetadata('roles', ['admin']) getAdminDashboard() { return { message: 'Welcome to the admin dashboard!' }; } }
In this example, the RolesGuard
will check if the user has the "admin" role before allowing access to the dashboard
route.
This article provides a foundational understanding of authorization in NestJS using Guards. We covered the basics of creating a guard, applying it to routes, and how to extend that to include role-based authorization. This should give you a solid start to securing your NestJS applications effectively with Guards. As you continue exploring NestJS, you’ll find even more ways to customize and extend guards to meet your application’s specific needs.
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS