Careeroza
What is a Guard
Allow or Deny
A guard decides whether a request may reach the handler. It returns true (continue) or false (NestJS throws ForbiddenException, 403). It can also throw its own exception, for example UnauthorizedException (401).
Unlike middleware, a guard gets an ExecutionContext, so it knows which class and method will run and can read their metadata.
src/common/guards/api-key.guard.ts
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import type { Request } from 'express';
@Injectable()
export class ApiKeyGuard implements CanActivate {
constructor(private readonly config: ConfigService) {}
canActivate(context: ExecutionContext): boolean {
const req = context.switchToHttp().getRequest<Request>();
const key = req.headers['x-api-key'];
if (key !== this.config.get('INTERNAL_API_KEY')) throw new UnauthorizedException('Invalid API key');
return true;
}
}Using It
@Controller('admin/reports')
@UseGuards(ApiKeyGuard)
export class ReportsController {
@Get('daily-sales')
dailySales() { return { date: '2026-01-15', orders: 1842, revenue: 2457300 }; }
}Example
curl -i http://localhost:3000/admin/reports/daily-sales
curl -H "x-api-key: s3cr3t" http://localhost:3000/admin/reports/daily-salesExample output
HTTP/1.1 401 Unauthorized
{"message":"Invalid API key","error":"Unauthorized","statusCode":401}
{"date":"2026-01-15","orders":1842,"revenue":2457300}Tip: canActivate may also return a Promise<boolean> or an Observable, so a guard can check the database.