Guards
Guards decide whether a request is allowed to proceed, making them ideal for authentication.
canActivate(context): booleanA guard answers a single yes/no question: should this request be handled? Return true and the request continues; return false and Nest responds with 403 Forbidden.
Where guards shine
Guards run after middleware but before interceptors and pipes, and they know exactly which handler will run. That makes them the right place for authentication and authorization.
A guard implements CanActivate. Apply it with @UseGuards() on a handler, a controller, or globally.
Example
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
@Injectable()
export class ApiKeyGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return request.headers['x-api-key'] === 'secret';
}
}
// @UseGuards(ApiKeyGuard) on a controller or routeWhen to use it
- A developer creates a JwtAuthGuard that validates the Bearer token on every protected route, returning 403 if verification fails.
- A team implements a RolesGuard that reads custom metadata set by a @Roles("admin") decorator to restrict endpoint access by role.
- An engineer applies @UseGuards(ThrottleGuard) at the controller level to rate-limit all routes in that controller without touching each handler.
More examples
Simple auth guard
Shows the minimal CanActivate guard that blocks requests missing the correct API key header.
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(ctx: ExecutionContext): boolean {
const request = ctx.switchToHttp().getRequest();
return Boolean(request.headers['x-api-key'] === process.env.API_KEY);
}
}Applying guard to controller
Protects all routes in AdminController by applying AuthGuard at the class level with @UseGuards.
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from './auth.guard';
@Controller('admin')
@UseGuards(AuthGuard) // applies to every route in this controller
export class AdminController {
@Get('stats')
getStats() { return { users: 42 }; }
}Global guard in bootstrap
Registers a guard globally in main.ts so every route in the entire application requires a valid JWT.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { JwtAuthGuard } from './auth/jwt-auth.guard';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalGuards(new JwtAuthGuard());
await app.listen(3000);
}
bootstrap();
Discussion