iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
A NestJS guard decides whether a request may proceed to a route handler. Implement the decision in canActivate(), use ExecutionContext to identify the handler and active transport, and use Reflector when the decision depends on metadata such as roles or a public-route marker. This guide follows the cited NestJS v10 guard and authorization guidance and v11 execution-context guidance; check the documentation for your project’s installed major version before adopting version-sensitive examples.
What a NestJS guard does
A guard is a route-aware gate in Nest’s request lifecycle. It runs after middleware and before pipes, and can determine which controller and handler are about to execute. Middleware generally does not have that route execution context. See the NestJS v10 Guards documentation.
Authentication and authorization are related but different tasks. Authentication establishes who the caller is; authorization decides whether that caller may invoke a particular handler. A guard can perform authorization using a user established by an earlier authentication step, or participate in an authentication design itself. The authentication mechanism and where the user is attached are application-specific.
Implement the CanActivate decision
A guard implements the CanActivate interface and provides canActivate(). It may return a boolean immediately, a Promise of a boolean, or an Observable of a boolean. A true result allows the request to continue; false denies it. In the cited v10 documentation, returning false causes Nest to throw an HttpException. Throw a specific exception from the guard when the application needs a different response.
#1 Best Overall
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
@Injectable()
export class ExampleGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return Boolean(request.user);
}
}
This example is HTTP-specific. It assumes an earlier authentication step has placed a user on the request; it is not a complete authentication system or a transport-neutral guard.
Use ExecutionContext for the route and transport
ExecutionContext extends ArgumentsHost. It exposes the handler about to run through getHandler(), the controller class through getClass(), and methods for accessing arguments in the active transport. The v11 Execution context documentation describes these APIs.
context.getHandler()returns the route handler function.context.getClass()returns the controller class.context.switchToHttp().getRequest()accesses the HTTP request when the guard is running in an HTTP context.
Do not assume every context contains an HTTP request. For RPC and WebSocket handlers, use the corresponding context switch and argument shape. GraphQL has its own integration-specific context access. A guard can be shared across transports, but the code that retrieves the caller and transport data must match the active framework context.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchRead route metadata with Reflector
Use Nest’s Reflector service to read metadata set on a handler or controller. get() reads metadata from one target. When a policy may be declared at both levels, getAllAndOverride() and getAllAndMerge() let the guard define how those values interact.
Rank #3
Override: handler policy takes precedence
getAllAndOverride() checks targets in the order supplied and returns the first defined metadata value. Put the handler before the controller when method-level metadata should override controller-level metadata:
const roles = this.reflector.getAllAndOverride<string[]>('roles', [
context.getHandler(),
context.getClass(),
]);
With this ordering, a method declaration takes precedence when present; otherwise the controller declaration can apply.
Rank #4
Merge: combine values from both targets
getAllAndMerge() combines metadata values from the supplied targets rather than selecting the first defined one. This is useful only when combining declarations is the intended policy—for example, when a method’s values should add to the controller’s values. Choose deliberately: merging roles and overriding roles have different authorization consequences. The v11 Execution context documentation covers metadata lookup methods.
Build a reusable roles guard
A common pattern is to attach role metadata at the controller or handler, then have one guard retrieve the applicable roles and compare them with the authenticated user. This illustrative example uses handler-over-controller precedence and assumes request.user.roles is populated by the application’s authentication layer.
Best Value
import {
CanActivate,
ExecutionContext,
Injectable,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.getAllAndOverride<string[]>(
'roles',
[context.getHandler(), context.getClass()],
);
if (!requiredRoles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
return requiredRoles.some((role) => user?.roles?.includes(role));
}
}
The example uses an HTTP request and a simple role-membership check. Define the metadata key and role model consistently in the application, and adapt caller/context access for GraphQL, RPC, or WebSocket handlers rather than reusing the HTTP request lookup unchanged. Nest’s v10 authorization guide demonstrates authorization metadata and guards.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Choose where to bind a guard
Nest guards can be bound to an individual method, a controller, or the whole application. Choose the narrowest scope that matches the policy, and verify dependency-injection behavior for the chosen binding.
- Method: apply a guard to a single handler when only that route needs the policy.
- Controller: apply it to all handlers in a controller when they share a rule.
- Application: use a global guard for a policy intended to cover the application’s routes.
The v10 Guards guide documents method, controller, and application-level binding. It also shows useGlobalGuards() for application-level registration. If a global guard needs injected providers, register it through the module provider system with APP_GUARD; the v8 Authentication guide demonstrates that provider pattern. Confirm the exact setup against the NestJS major version used by the project.
Quick Recap
Common mistakes to avoid
- Using middleware for a route-specific decision: middleware does not have the same handler-aware
ExecutionContextthat a guard receives. - Reversing metadata target order: with
getAllAndOverride(), the first defined target wins. Put the method first if it should override the controller. - Confusing merge and override: merging values can broaden or otherwise change a policy; use it only when combined declarations are intended.
- Assuming an authenticated user exists: the guard must run after the application’s authentication step, or otherwise establish identity before relying on user data.
- Assuming every request is HTTP: use transport-appropriate context access for GraphQL, RPC, and WebSockets.
- Returning false when a specific denial is required: the cited v10 guide specifies Nest throws an
HttpExceptionfor false; throw the desired exception when the response must differ.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

