The Most Common Use of Guards
Auth Guards
Auth guards check a token or session, attach the authenticated user to the request, and either let it through or reject it.
What you'll learn
- Write a JWT-validating guard from scratch
- Use AuthGuard from @nestjs/passport for built-in strategies
- Stack guards (authentication, then authorization)
Auth is the canonical guard use case. A guard reads a token from the request, verifies it, looks up the user, and either continues or rejects.
A Hand-Rolled JWT Guard
If you only need JWT validation, you don’t have to pull in Passport at all.
import {
CanActivate, ExecutionContext, Injectable, UnauthorizedException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class JwtAuthGuard implements CanActivate {
constructor(private readonly jwt: JwtService) {}
async canActivate(ctx: ExecutionContext): Promise<boolean> {
const req = ctx.switchToHttp().getRequest();
const auth = req.headers.authorization ?? '';
const [scheme, token] = auth.split(' ');
if (scheme !== 'Bearer' || !token) {
throw new UnauthorizedException('missing bearer token');
}
try {
req.user = await this.jwt.verifyAsync(token);
return true;
} catch {
throw new UnauthorizedException('invalid token');
}
}
} Apply it like any other guard:
@Controller('me')
@UseGuards(JwtAuthGuard)
export class MeController {
@Get()
me(@Req() req: Request) {
return req.user; // populated by the guard
}
} Using Passport Strategies
When you want OAuth, sessions, or other strategies, @nestjs/passport
wraps Passport’s library and exposes guards keyed by strategy name.
import { AuthGuard } from '@nestjs/passport';
// 'jwt' is the strategy name registered in your auth module
export class JwtAuthGuard extends AuthGuard('jwt') {}
@Controller('protected')
@UseGuards(JwtAuthGuard)
export class ProtectedController {
@Get() data() { return 'top secret'; }
} The matching JwtStrategy (a separate class that extends PassportStrategy)
does the actual verification — the guard just plugs Passport into Nest’s
pipeline.
Stacking Authentication and Authorization
You almost always want two layers: authn (“who are you?”) and authz (“are
you allowed to do this?”). @UseGuards accepts multiple — they run in
order, short-circuiting on the first failure.
@Delete(':id')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
remove(@Param('id') id: string) {
return this.users.remove(id);
} JwtAuthGuard runs first and attaches req.user. RolesGuard then reads
the @Roles metadata and req.user.roles to decide. (You’ll build that
roles guard in the metadata lesson.)
Optional Auth
Sometimes you want a route that works for both anonymous and authenticated
users — return personalized content if logged in, public content otherwise.
Solve it with a “passive” guard that always returns true but still
attempts to attach a user:
async canActivate(ctx: ExecutionContext): Promise<boolean> {
try { await this.attachUserIfPresent(ctx); } catch { /* ignore */ }
return true;
} Auth guards are usually the first thing you wire into a serious Nest app. Get them right and the rest of your security model has a stable foundation.
Interceptors — Wrap the Pipeline →