Menu
CoddyTech

Guards

Part of the TypeScript and NestJS section of Coddy's Node.js journey. Lesson 18 of 24.

Anyone can create or delete tasks. A guard decides whether a request may reach its handler: Nest calls its canActivate, and when it returns false, Nest answers 403 Forbidden without running the method.

@Injectable()
export class OpenHoursGuard implements CanActivate {
    canActivate(context: ExecutionContext): boolean {
        const hour = new Date().getHours();
        return hour >= 9 && hour < 17;
    }
}

@Post()
@UseGuards(OpenHoursGuard)
book() {}

context.switchToHttp().getRequest() gives the request; Node stores its header names in lower case, so read request.headers['x-api-key']. @UseGuards on a method guards that method. On the controller class it guards every method in it.

challenge icon

Challenge

Easy

Right now anyone can create or delete tasks. Lock the two routes that change data behind an API key: a secret that the client sends in a request header. Reading stays open to everyone.

  1. Open src/common/api-key.guard.ts. In ApiKeyGuard's canActivate method, read the x-api-key header of the request. context.switchToHttp().getRequest() gives you the request, and its header names are always lower case.
  2. Return true only when that header equals process.env.API_KEY, which this lesson sets to tasks-key-123. Return false in every other case, including when the header is missing. When the guard returns false, Nest responds with 403 and never runs the route's method.
  3. In src/tasks/tasks.controller.ts, import ApiKeyGuard from ../common/api-key.guard, and UseGuards from @nestjs/common. Put @UseGuards(ApiKeyGuard) on the create method (POST /tasks) and on the remove method (DELETE /tasks/:id). Do not put it on the class: that would lock the GET routes too.
  4. GET /tasks, GET /tasks/:id and GET /stats keep working without a key.

Try it: POST { "title": "Buy milk" } to /tasks with no header. You get 403:

{ "message": "Forbidden resource", "error": "Forbidden", "statusCode": 403 }

Open the Headers field of the request bar, add the line x-api-key: tasks-key-123, and send the POST again: 201 and the new task. With x-api-key: guess you get 403. DELETE /tasks/4 needs the key too: 403 without it, 204 with it. GET /tasks works with no header at all.

Try it yourself

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';

@Injectable()
export class ApiKeyGuard implements CanActivate {
    canActivate(context: ExecutionContext): boolean {
        // Let the request through only when its x-api-key header
        // equals process.env.API_KEY.
        return true;
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in TypeScript and NestJS

Practice on your own: Express playground