Guards
Guards are a powerful mechanism for implementing authorization logic in your application. They determine whether a request should be handled by the route handler or not, making them perfect for authentication, authorization, and access control scenarios.
💡 Key Concept: Guards execute after all middleware but before pipes and route handlers. They have access to the full execution context and can make complex authorization decisions.
Guard Interface
Guards implement the CanActivate interface, which defines a single method:
import { CanActivate, HttpGuardExecutionContext } from '@nl-framework/http';export class AuthGuard implements CanActivate { async canActivate(context: HttpGuardExecutionContext): Promise<boolean> { const request = context.getRequest(); const token = request.headers.authorization; if (!token) { return false; } try { const user = await this.validateToken(token); request.user = user; return true; } catch (error) { return false; } } private async validateToken(token: string) { return { id: 1, username: 'john' }; }}Using Guards
Guards can be applied to controllers or individual route handlers using the @UseGuards() decorator:
Method-Level Guards
import { Controller, Get, UseGuards } from '@nl-framework/http';@Controller('/api/users')export class UserController { @Get('/') @UseGuards(AuthGuard) async getUsers() { return { users: [] }; } @Get('/public') async getPublicData() { return { data: 'public' }; }}Controller-Level Guards
@Controller('/api/admin')@UseGuards(AuthGuard, AdminGuard)export class AdminController { @Get('/users') async getUsers() { return { users: [] }; } @Delete('/users/:id') async deleteUser(id: string) { return { deleted: true }; }}Functional Guards
For simple authorization logic, you can use functional guards instead of classes:
import { GuardFunction } from '@nl-framework/http';const isAuthenticated: GuardFunction = async (context) => { const request = context.getRequest(); return !!request.headers.authorization;};function hasRole(role: string): GuardFunction { return async (context) => { const request = context.getRequest(); return request.user?.role === role; };}@Controller('/api/admin')export class AdminController { @Get('/dashboard') @UseGuards(isAuthenticated, hasRole('admin')) async getDashboard() { return { dashboard: {} }; }}Global Guards
Register guards globally to apply them to all routes:
import { createHttpApp, registerHttpGuard } from '@nl-framework/http';async function bootstrap() { const app = await createHttpApp({ port: 3000 }); registerHttpGuard(AuthGuard); await app.start();}Advanced Patterns
Role-Based Access Control (RBAC)
import { SetMetadata } from '@nl-framework/core';export const Roles = (...roles: string[]) => SetMetadata('roles', roles);@Injectable()export class RolesGuard implements CanActivate { async canActivate(context: HttpGuardExecutionContext): Promise<boolean> { const requiredRoles = context.getRoute().metadata?.roles as string[]; if (!requiredRoles) return true; const user = context.getRequest().user; return requiredRoles.some(role => user.roles?.includes(role)); }}@Controller('/api/admin')@UseGuards(AuthGuard, RolesGuard)export class AdminController { @Get('/users') @Roles('admin', 'superadmin') async getUsers() { return { users: [] }; }}Best Practices
✅ Summary: Guards provide a clean, declarative way to implement authorization logic. They execute after middleware but before pipes and handlers, support both class-based and functional implementations, and can be applied globally, per-controller, or per-route.