📖 Scenario: You are building a NestJS application that needs to control access to routes using guards. Guards can be applied at different levels: method, controller, and global. Understanding how to bind guards at these levels helps you manage security effectively.
🎯 Goal: Build a NestJS app demonstrating guard binding at method, controller, and global levels. You will create a simple guard and apply it step-by-step to see how NestJS handles guard execution order.
📋 What You'll Learn
Create a simple guard class called AuthGuard that implements CanActivate.
Apply AuthGuard to a single route method.
Apply AuthGuard to a controller class.
Apply AuthGuard globally using app.useGlobalGuards().
💡 Why This Matters
🌍 Real World
Guards are used in real NestJS apps to protect routes based on authentication or roles. Knowing how to bind guards at different levels helps organize security cleanly.
💼 Career
Understanding guard binding levels is essential for backend developers working with NestJS to implement secure APIs and control access efficiently.
Progress0 / 4 steps
1
Create the AuthGuard class
Create a class called AuthGuard that implements CanActivate interface. Inside the canActivate method, return true to allow access.
NestJS
Hint
Use implements CanActivate and define canActivate method returning true.
2
Apply AuthGuard to a route method
In a controller class called AppController, create a method called getHello decorated with @Get(). Apply the AuthGuard to this method using @UseGuards(AuthGuard). The method should return the string 'Hello World'.
NestJS
Hint
Use @UseGuards(AuthGuard) above the getHello method.
3
Apply AuthGuard to the controller
Modify the AppController class to apply AuthGuard at the controller level by adding @UseGuards(AuthGuard) above the class declaration. Remove the guard from the getHello method.
NestJS
Hint
Place @UseGuards(AuthGuard) above @Controller() and remove it from the method.
4
Apply AuthGuard globally
In the main application bootstrap function, apply AuthGuard globally by calling app.useGlobalGuards(new AuthGuard()). Assume app is the NestJS application instance.
NestJS
Hint
Call app.useGlobalGuards(new AuthGuard()) inside the bootstrap function before app.listen().
Practice
(1/5)
1. Which of the following is true about guard binding levels in NestJS?
easy
A. Route guards apply to all controllers automatically.
B. Global guards apply to all routes in the application.
C. Controller guards cannot be overridden by route guards.
D. Guards can only be applied globally, not to specific routes.
Solution
Step 1: Understand global guard scope
Global guards are set once and protect every request in the app.
Step 2: Compare with other guard levels
Route guards apply only to specific routes, and controller guards apply to all routes in a controller. Route guards can override controller guards.
Final Answer:
Global guards apply to all routes in the application. -> Option B
Quick Check:
Global guard = all routes [OK]
Hint: Global guards protect all routes, no exceptions [OK]
Common Mistakes:
Thinking route guards apply globally
Believing controller guards cannot be overridden
Assuming guards can't be applied to routes
2. Which is the correct way to bind a guard to a specific route in NestJS?
easy
A. Use @GlobalGuard decorator on the route
B. @UseGuards(MyGuard) above the controller class
C. Add MyGuard to the global providers array
D. @UseGuards(MyGuard) above the route handler method
Solution
Step 1: Identify route-level guard binding
To bind a guard to a specific route, place @UseGuards() decorator above the route handler method.
Step 2: Differentiate from other bindings
@UseGuards() above the controller binds to all routes in that controller. Global guards are set differently, and @GlobalGuard does not exist.
Final Answer:
@UseGuards(MyGuard) above the route handler method -> Option D
Quick Check:
Route guard = @UseGuards on method [OK]
Hint: Use @UseGuards on method for route-level guards [OK]
Common Mistakes:
Putting @UseGuards only on controller for route guard
Confusing global providers with route guards
Using non-existent @GlobalGuard decorator
3. Given this code snippet, what will happen when a request hits the GET /users/profile route?
A. GlobalGuard, ControllerGuard, and RouteGuard all run in order.
B. Only GlobalGuard runs before the route handler.
C. Only RouteGuard runs, ignoring others.
D. ControllerGuard overrides and disables other guards.
Solution
Step 1: Identify guard binding levels in code
GlobalGuard is bound globally, ControllerGuard on the controller, and RouteGuard on the route method.
Step 2: Understand guard execution order
All guards bound at different levels run in order: global first, then controller, then route.
Final Answer:
GlobalGuard, ControllerGuard, and RouteGuard all run in order. -> Option A
Quick Check:
All guards run in binding order [OK]
Hint: All guards at different levels run in sequence [OK]
Common Mistakes:
Assuming only one guard runs
Thinking controller guard disables others
Believing global guard runs alone
4. You have a guard bound globally and another bound to a controller. The controller guard is not running on requests. What is the likely cause?
medium
A. The controller guard was not added to the controller with @UseGuards.
B. Controller guards cannot be used with global guards.
C. Guards must be bound only at one level, not multiple.
D. The global guard is blocking all requests before the controller guard runs.
Solution
Step 1: Check guard binding syntax
Controller guards must be explicitly added with @UseGuards on the controller class.
Step 2: Understand guard coexistence
Global and controller guards can coexist; global guards do not block controller guards from running.
Final Answer:
The controller guard was not added to the controller with @UseGuards. -> Option A
Quick Check:
Missing @UseGuards on controller = no controller guard [OK]
Hint: Always add @UseGuards to controller for controller guards [OK]
Common Mistakes:
Thinking global guard blocks controller guards
Believing guards can't be combined
Forgetting to decorate controller with @UseGuards
5. You want to apply a guard that blocks access to all routes except one specific route in a controller. Which approach correctly uses guard binding levels to achieve this?
hard
A. Bind the guard globally and use a route-level guard to allow the exception route.
B. Bind the guard only on the exception route to block all others.
C. Bind the guard on the controller and override it with a route-level guard that allows the exception.
D. Bind the guard globally and remove it from the exception route using @SkipGuards.
Solution
Step 1: Understand guard override behavior
Controller-level guards apply to all routes in that controller but can be overridden by route-level guards.
Step 2: Apply guard to block all except one route
Binding the guard on the controller blocks all routes; then a route-level guard on the exception route can allow access.
Final Answer:
Bind the guard on the controller and override it with a route-level guard that allows the exception. -> Option C