0
0
NestjsHow-ToBeginner ยท 4 min read

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 | Observable 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 canActivate leads 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.

ConceptDescription
@Injectable()Marks the guard class for dependency injection
CanActivateInterface to implement for creating a guard
canActivate()Method that returns boolean or Promise/Observable to allow or deny access
@UseGuards()Decorator to apply guard to controllers or routes
ExecutionContextProvides 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.