How to use guards and implement authentication

Let's understand NestJS guard function and implement authentication.

overview

NestJS has a feature called a guard to decide whether to continue processing the request. Guards are available by implementing the CanActivate interface, and are most commonly used to handle authentication.

Guards have two main roles:

  1. Authentication: User privileges, roles, and ACLs are verified to determine whether to continue processing the request.
  2. Request Control: Works between middleware and interceptors to control request processing.

This article explains how to use NestJS guards and how to implement authentication using guards.

Creating and using guards

You can create guards using NestJS’s CLI tools. Running the following command will create a guard named AuthGuard.

nest g guard users/guard/auth

The created guard implements the CanActivate interface and has a canActivate method. This method is for deciding whether to continue processing the request.

Below is an example guard that rejects the request if the query parameter is not present.

/src/users/guard/auth/auth.guard.ts

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

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
    return !!request.query.params;
  }
}

In the code above, the canActivate method checks the query parameters of the request and only continues processing the request if the params parameter is present.

To use the created guards, bind them to your controllers or route handlers using the @UseGuards decorator. An example is shown below.

import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  HttpException,
  HttpStatus,
  Use filters,
  Parse Int Pipe,
  Use Guards,
} from '@nestjs/common';
import { UsersService } from './users.service';
import { ForbiddenException } from './exceptions/forbidden.exception';
import { HttpExceptionFilter } from './filters/http-exception/http-exception.filter';
import { AuthGuard } from './guard/auth/auth.guard';

@Controller('users')
@UseFilters(new HttpExceptionFilter())
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  getUsers(): User[] {
    return this.usersService.getUsers();
  }
  @Post()
  addUser(@Body() name: string): void {
    this.usersService.addUser(name);
  }
  @Put(':id')
  putUser(
    @Param('id', ParseIntPipe) id: number,
    @Body('name') name: string,
  ): void {
    this.usersService.putUser(id, name);
  }
  @Delete(':id')
  deleteUser(@Param('id', ParseIntPipe) id: number): void {
    this.usersService.deleteUser(id);
  }
  @Get('throw')
  getException(): string {
    throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
  }
  @Get('custom_throw')
  getCustomException(): string {
    throw new ForbiddenException();
  }
  @Get('guard')
  @UseGuards(AuthGuard)
  getGuard(): string {
    return 'Guard is working';
  }
}

The above code uses the @UseGuards decorator to bind AuthGuard to the getHello route handler. With this, when there is a request to getHello, the canActivate method of AuthGuard will be executed first, and the request processing will continue based on the result.

test

## If there is no parameter, it will not pass.
curl http://localhost:3000/users/guard
## Passes if there are parameters.
curl http://localhost:3000/users/guard?params=true

summary

Guards in NestJS are powerful features that determine whether or not to continue processing a request. In particular, when performing user authentication and authority verification, the use of guards enables efficient processing. Understand how to use guards and use them appropriately.