In modern web development, managing user access and permissions is crucial for maintaining security and ensuring a good user experience. NestJS, a progressive Node.js framework, provides a powerful feature called decorators that simplifies implementing authorization checks. This article explores practical examples of using decorators for authorization in NestJS, helping developers secure their APIs effectively.

Understanding Decorators in NestJS

Decorators in NestJS are special functions that can be attached to classes, methods, or parameters to add metadata or modify behavior. They are inspired by TypeScript decorators and enable clean, declarative code. For authorization, decorators can be used to specify who can access certain endpoints based on roles or permissions.

Creating a Custom Role Decorator

To implement role-based access control, start by creating a custom decorator that extracts roles from route handlers. Here's an example:

import { SetMetadata } from '@nestjs/common';

export const ROLES_KEY = 'roles';

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

Implementing Role Guard

Next, create a guard that reads the roles metadata and verifies if the current user has the required roles:

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

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

  canActivate(context: ExecutionContext): boolean {
    const roles = this.reflector.get(ROLES_KEY, context.getHandler());
    if (!roles) {
      return true;
    }
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    return user && user.roles && roles.some(role => user.roles.includes(role));
  }
}

Applying Decorators and Guards

Use the @Roles decorator and the RolesGuard in your controllers to protect routes:

import { Controller, Get, UseGuards } from '@nestjs/common';

@Controller('admin')
@UseGuards(RolesGuard)
export class AdminController {
  @Get()
  @Roles('admin')
  getAdminData() {
    return { message: 'This is admin data' };
  }
}

Practical Tips for Using Decorators

  • Combine multiple roles by passing them as arguments to the @Roles decorator.
  • Use custom guards for complex authorization logic beyond roles.
  • Leverage metadata to make your authorization logic flexible and reusable.
  • Secure all sensitive endpoints with appropriate guards and decorators.

Conclusion

Decorators in NestJS provide a clean and efficient way to implement authorization checks. By creating custom decorators and guards, developers can enforce role-based access control seamlessly. These practical examples serve as a foundation for building secure and maintainable APIs with NestJS.