What are guards in NestJS and how to implement authentication?
Guards in NestJS
Guards determine whether a request should be handled by the route handler or not. They implement the CanActivate interface and return true (allow) or false (deny). Guards are most commonly used for authentication and authorization.
Creating a Guard
typescript
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
return this.validateRequest(request);
}
private validateRequest(request: any): boolean {
return !!request.headers.authorization;
}
}JWT Auth Guard
typescript
// guards/jwt-auth.guard.ts
import {
Injectable, CanActivate, ExecutionContext, UnauthorizedException
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Request } from 'express';
@Injectable()
export class JwtAuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest<Request>();
const token = this.extractToken(request);
if (!token) throw new UnauthorizedException('No token provided');
try {
const payload = await this.jwtService.verifyAsync(token, {
secret: process.env.JWT_SECRET,
});
request['user'] = payload; // attach to request
return true;
} catch {
throw new UnauthorizedException('Invalid or expired token');
}
}
private extractToken(request: Request): string | null {
const [type, token] = request.headers.authorization?.split(' ') ?? [];
return type === 'Bearer' ? token : null;
}
}Roles Guard (Authorization)
typescript
// guards/roles.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ROLES_KEY } from '../decorators/roles.decorator';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.getAllAndOverride<string[]>(
ROLES_KEY,
[context.getHandler(), context.getClass()],
);
if (!requiredRoles) return true; // no roles required โ allow
const { user } = context.switchToHttp().getRequest();
return requiredRoles.some(role => user.roles?.includes(role));
}
}
// decorators/roles.decorator.ts
import { SetMetadata } from '@nestjs/common';
export const ROLES_KEY = 'roles';
export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);Applying Guards
typescript
// Method-level
@Get('profile')
@UseGuards(JwtAuthGuard)
getProfile(@Request() req) {
return req.user;
}
// Controller-level
@Controller('admin')
@UseGuards(JwtAuthGuard, RolesGuard)
export class AdminController {}
// Global (all routes)
// main.ts
app.useGlobalGuards(new JwtAuthGuard(jwtService));
// Or via module (preferred โ supports DI)
@Module({
providers: [
{ provide: APP_GUARD, useClass: JwtAuthGuard },
],
})Public Routes Decorator
typescript
// decorators/public.decorator.ts
export const IS_PUBLIC_KEY = 'isPublic';
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
// In JwtAuthGuard.canActivate():
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
context.getHandler(),
context.getClass(),
]);
if (isPublic) return true; // skip auth for @Public() routes
// Usage:
@Public()
@Post('auth/login')
login(@Body() loginDto: LoginDto) { ... }Guard vs Middleware vs Interceptor
| Guard | Middleware | Interceptor | |
|---|---|---|---|
Has ExecutionContext | โ | โ | โ |
| Can access metadata | โ | โ | โ |
| Purpose | Auth / Authorization | Logging, CORS | Transform response |
| Can abort request | โ | โ | โ |
Summary
Guards are the security layer of NestJS. Implement CanActivate, access the request via ExecutionContext, and return true or throw UnauthorizedException. Use Reflector + custom metadata decorators (like @Roles()) for fine-grained role-based access control.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.