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
EasyRight 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.
- Open
src/common/api-key.guard.ts. InApiKeyGuard'scanActivatemethod, read thex-api-keyheader of the request.context.switchToHttp().getRequest()gives you the request, and its header names are always lower case. - Return
trueonly when that header equalsprocess.env.API_KEY, which this lesson sets totasks-key-123. Returnfalsein every other case, including when the header is missing. When the guard returnsfalse, Nest responds with 403 and never runs the route's method. - In
src/tasks/tasks.controller.ts, importApiKeyGuardfrom../common/api-key.guard, andUseGuardsfrom@nestjs/common. Put@UseGuards(ApiKeyGuard)on thecreatemethod (POST /tasks) and on theremovemethod (DELETE /tasks/:id). Do not put it on the class: that would lock the GET routes too. GET /tasks,GET /tasks/:idandGET /statskeep 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;
}
}
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