Discover how a simple guard can protect your app like a vigilant gatekeeper!
Why Protected routes with guards in NestJS? - Purpose & Use Cases
Imagine building a web app where some pages should only be seen by logged-in users. You try to check user access on every route manually by writing checks inside each route handler.
Manually checking access in every route is tiring and easy to forget. It leads to repeated code, mistakes, and security holes if you miss a check. It also makes your code messy and hard to maintain.
Protected routes with guards let you write access rules once and apply them automatically to routes. Guards act like gatekeepers that decide if a user can enter a route, keeping your code clean and secure.
if (!user.isLoggedIn) { return 'Access denied'; } // repeated in every route
@UseGuards(AuthGuard) // applied once to protect routes
This makes it easy to secure your app by centralizing access control, improving security and code clarity.
Think of a club with a bouncer (guard) who checks IDs at the door instead of each room having its own checker. Only allowed guests get in smoothly.
Manual access checks are repetitive and error-prone.
Guards centralize and automate route protection.
Using guards improves security and keeps code clean.
Practice
Solution
Step 1: Understand the role of guards
Guards in NestJS are designed to control access to routes by running custom logic before the route handler executes.Step 2: Identify the correct purpose
Among the options, only deciding if a request can access a route matches the guard's role.Final Answer:
To decide if a request can access a route based on custom logic -> Option AQuick Check:
Guards control access = C [OK]
- Confusing guards with interceptors or middleware
- Thinking guards modify response data
- Assuming guards handle database tasks
Solution
Step 1: Recall the decorator for guards
The correct decorator to apply guards in NestJS is@UseGuards().Step 2: Identify correct placement
This decorator can be placed before a route handler method or a controller class. @UseGuards(AuthGuard) before the route handler method correctly shows it before a route handler method.Final Answer:
@UseGuards(AuthGuard) before the route handler method -> Option BQuick Check:
@UseGuards + route method = D [OK]
- Using @Guard or @ApplyGuard which don't exist
- Placing decorators inside constructor
- Confusing middleware with guards
import { CanActivate, ExecutionContext } from '@nestjs/common';
export class AlwaysDenyGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
return false;
}
}Applied to a route, what is the result?
Solution
Step 1: Analyze the canActivate method
The guard's canActivate method always returns false, meaning it denies access.Step 2: Understand guard effect on route
When canActivate returns false, NestJS blocks the request and does not run the route handler.Final Answer:
The request is blocked and the route handler does not run -> Option CQuick Check:
canActivate false blocks request = A [OK]
- Thinking false lets the route run
- Assuming guard throws error on false
- Confusing logging with blocking
import { CanActivate, ExecutionContext } from '@nestjs/common';
export class MyGuard implements CanActivate {
canActivate(context: ExecutionContext) {
if (context.switchToHttp().getRequest().user) {
return true;
}
}
}Solution
Step 1: Check canActivate return paths
The method returns true if user exists, but returns nothing (undefined) otherwise.Step 2: Understand guard return requirements
canActivate must always return a boolean or Promise<boolean>. Missing return means undefined, which is invalid.Final Answer:
Missing return statement when user is not present -> Option DQuick Check:
All paths must return boolean = B [OK]
- Forgetting else return false
- Assuming undefined is false
- Thinking async is always required
import { CanActivate, ExecutionContext } from '@nestjs/common';
export class RolesGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const user = request.user;
// Which condition correctly checks for admin role?
}
}Solution
Step 1: Understand user role structure
Assuming user has a single role string in propertyrole, not an array.Step 2: Check each condition
return user && user.role === 'admin'; correctly comparesuser.role === 'admin'. return user && user.roles.includes('admin'); assumes roles is an array, which may be incorrect. Options C and D misuse property types.Final Answer:
return user && user.role === 'admin'; -> Option AQuick Check:
Check user.role string equals 'admin' = A [OK]
- Confusing roles array with single role string
- Using includes on a string property
- Checking wrong property name
Ready to prove it?
Pass the test and this pattern moves unknown
