How to Create Guard in NestJS: Simple Guide with Example
In NestJS, create a guard by implementing the
CanActivate interface and defining the canActivate method. Then, apply the guard to routes or controllers using the @UseGuards() decorator to control access.Syntax
A guard in NestJS is a class that implements the CanActivate interface. It must have a canActivate(context: ExecutionContext): boolean | Promise method that returns true to allow the request or false to deny it.
Use the @Injectable() decorator to make the guard injectable. Apply the guard with @UseGuards(YourGuard) on controllers or route handlers.
typescript
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Observable } from 'rxjs'; @Injectable() export class YourGuard implements CanActivate { canActivate( context: ExecutionContext, ): boolean | Promise<boolean> | Observable<boolean> { // Your logic here return true; // or false } } // Usage in controller import { Controller, Get, UseGuards } from '@nestjs/common'; @Controller('example') @UseGuards(YourGuard) export class ExampleController { @Get() getData() { return 'Protected data'; } }
Example
This example shows a simple guard that allows access only if a custom header x-api-key equals a secret key. It protects a route that returns a message if access is granted.
typescript
import { Injectable, CanActivate, ExecutionContext, Controller, Get, UseGuards } from '@nestjs/common'; import { Observable } from 'rxjs'; @Injectable() export class ApiKeyGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest(); const apiKey = request.headers['x-api-key']; return apiKey === 'secret123'; } } @Controller('secure') @UseGuards(ApiKeyGuard) export class SecureController { @Get() getSecret() { return 'Access granted to secret data'; } }
Output
If request header 'x-api-key' equals 'secret123', response: "Access granted to secret data"; otherwise, 403 Forbidden error.
Common Pitfalls
- Forgetting to add
@Injectable()to the guard class causes NestJS to fail dependency injection. - Not returning a boolean or a Promise/Observable resolving to boolean from
canActivateleads to unexpected behavior. - Applying the guard incorrectly by missing
@UseGuards()decorator or applying it to the wrong place. - Not handling asynchronous checks properly if your guard logic involves async calls.
typescript
/* Wrong: Missing @Injectable() */ export class MissingInjectableGuard implements CanActivate { canActivate() { return true; } } /* Right: With @Injectable() */ import { Injectable, CanActivate } from '@nestjs/common'; @Injectable() export class CorrectGuard implements CanActivate { canActivate() { return true; } }
Quick Reference
Guards control access by returning true or false in canActivate. Use @UseGuards() to apply them. Always mark guards with @Injectable(). Guards can be synchronous or asynchronous.
| Concept | Description |
|---|---|
| @Injectable() | Marks the guard class for dependency injection |
| CanActivate | Interface to implement for creating a guard |
| canActivate() | Method that returns boolean or Promise/Observable |
| @UseGuards() | Decorator to apply guard to controllers or routes |
| ExecutionContext | Provides details about the current request |
Key Takeaways
Create guards by implementing CanActivate and defining canActivate method.
Always use @Injectable() on guard classes for NestJS to inject dependencies.
Apply guards with @UseGuards() on controllers or route handlers.
Return true to allow access, false to deny, supporting async if needed.
Test guards carefully to avoid blocking valid requests or allowing unauthorized access.