0
0
NestJSframework~5 mins

Role-based guards in NestJS

Choose your learning style9 modes available
Introduction

Role-based guards help control who can access certain parts of your app based on their role. They keep your app safe by allowing only the right users to do specific actions.

You want only admins to access the admin dashboard.
You want to restrict editing rights to managers only.
You want to show certain pages only to logged-in users with specific roles.
You want to prevent guests from accessing user settings.
You want to protect API routes based on user roles.
Syntax
NestJS
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';

@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler());
    if (!requiredRoles) {
      return true;
    }
    const { user } = context.switchToHttp().getRequest();
    return requiredRoles.some(role => user.roles?.includes(role));
  }
}

The guard uses Reflector to read roles metadata set on route handlers.

The canActivate method returns true if the user has any required role.

Examples
This example shows how to set roles metadata on a route using a custom @Roles decorator.
NestJS
@Roles('admin')
@Get('admin')
getAdminData() {
  return 'Admin data';
}
This is the custom @Roles decorator that attaches roles metadata to routes.
NestJS
import { SetMetadata } from '@nestjs/common';

export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
Here, the RolesGuard protects the getProfile route, allowing only users with 'user' or 'admin' roles.
NestJS
@UseGuards(RolesGuard)
@Controller('users')
export class UsersController {
  @Roles('user', 'admin')
  @Get('profile')
  getProfile() {
    return 'User profile';
  }
}
Sample Program

This example shows a simple NestJS controller with two routes protected by the RolesGuard. Only users with the 'admin' role can access the admin dashboard, and only users with the 'user' role can access the user dashboard.

NestJS
import { Controller, Get, UseGuards } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { CanActivate, ExecutionContext, Injectable, SetMetadata } from '@nestjs/common';

export const Roles = (...roles: string[]) => SetMetadata('roles', roles);

@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler());
    if (!requiredRoles) {
      return true;
    }
    const { user } = context.switchToHttp().getRequest();
    return requiredRoles.some(role => user.roles?.includes(role));
  }
}

@UseGuards(RolesGuard)
@Controller('dashboard')
export class DashboardController {
  @Roles('admin')
  @Get('admin')
  getAdminDashboard() {
    return 'Welcome to Admin Dashboard';
  }

  @Roles('user')
  @Get('user')
  getUserDashboard() {
    return 'Welcome to User Dashboard';
  }
}
OutputSuccess
Important Notes

Make sure your authentication system adds a user object with roles to the request.

Use the @Roles decorator to specify which roles can access a route.

Guards run before route handlers to block unauthorized access early.

Summary

Role-based guards control access by checking user roles before running route code.

Use a custom @Roles decorator to mark routes with allowed roles.

Implement canActivate in a guard to allow or deny access based on roles.