typescript 72 lines · 8 steps

How guards chain auth in NestJS

Three NestJS guards run in sequence to authenticate, authorize by role, and check workspace membership on each request.

Explained by highlit
1import {
2 CanActivate,
3 ExecutionContext,
4 Injectable,
5 ForbiddenException,
6} from '@nestjs/common';
7import { Reflector } from '@nestjs/core';
8import { Request } from 'express';
9 
10@Injectable()
11export class JwtAuthGuard implements CanActivate {
12 canActivate(context: ExecutionContext): boolean {
13 const req = context.switchToHttp().getRequest<Request>();
14 const token = req.headers.authorization?.replace('Bearer ', '');
15 
16 if (!token) {
17 throw new ForbiddenException('Missing bearer token');
18 }
19 
20 req['user'] = this.decode(token);
21 return true;
22 }
23 
24 private decode(token: string) {
25 const [, payload] = token.split('.');
26 return JSON.parse(Buffer.from(payload, 'base64url').toString());
27 }
28}
29 
30@Injectable()
31export class RolesGuard implements CanActivate {
32 constructor(private readonly reflector: Reflector) {}
33 
34 canActivate(context: ExecutionContext): boolean {
35 const required = this.reflector.getAllAndOverride<string[]>('roles', [
36 context.getHandler(),
37 context.getClass(),
38 ]);
39 
40 if (!required?.length) {
41 return true;
42 }
43 
44 const { user } = context.switchToHttp().getRequest<Request>();
45 const granted = required.some((role) => user?.roles?.includes(role));
46 
47 if (!granted) {
48 throw new ForbiddenException('Insufficient role');
49 }
50 
51 return true;
52 }
53}
54 
55@Injectable()
56export class WorkspaceGuard implements CanActivate {
57 constructor(private readonly memberships: MembershipService) {}
58 
59 async canActivate(context: ExecutionContext): Promise<boolean> {
60 const req = context.switchToHttp().getRequest<Request>();
61 const isMember = await this.memberships.exists(
62 req['user'].sub,
63 req.params.workspaceId,
64 );
65 
66 if (!isMember) {
67 throw new ForbiddenException('Not a workspace member');
68 }
69 
70 return true;
71 }
72}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A guard is any class implementing canActivate that returns true to allow the request or throws to reject it.
  2. 2Chaining small single-purpose guards keeps authentication, role checks, and resource access independent and composable.
  3. 3Guards can attach data to the request object so later guards and handlers build on earlier work.

Related explainers

typescript
import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';
import localeFrExtra from '@angular/common/locales/extra/fr';
import localeDe from '@angular/common/locales/de';

Locale-aware bootstrapping in Angular

i18n localization dependency-injection
Intermediate 8 steps
typescript
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi';
 

Validating env config at boot in NestJS

configuration schema-validation environment-variables
Intermediate 8 steps
python
import time
import uuid
 
from django.utils.deprecation import MiddlewareMixin

Attaching per-request context in Django

middleware request lifecycle multi-tenancy
Intermediate 7 steps
typescript
import { Inject, Injectable, Logger } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { InjectRepository } from '@nestjs/typeorm';

A cache-aside country lookup in NestJS

cache-aside dependency-injection batch-lookup
Intermediate 8 steps
typescript
import { Injectable, effect, signal, computed } from '@angular/core';
 
interface Preferences {
  theme: 'light' | 'dark';

A signal-based preferences store in Angular

signals state-management persistence
Intermediate 7 steps
typescript
import { useEffect, useState } from "react";
 
interface Section {
  id: string;

Building a scroll-spy hook in React

custom-hooks intersectionobserver dom-observation
Intermediate 8 steps

Share this explainer

Here's the card — post it anywhere.

How guards chain auth in NestJS — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code