Role-Based Access Control in NestJS

  • Автор темы Автор темы Lomanu4
  • Дата начала Дата начала

Lomanu4

Команда форума
Администратор
Ofline
Role-Based Authorization in NestJS


Authorization is a critical aspect of application security. It ensures that users can access only the resources they’re permitted to. In NestJS, a progressive Node.js framework, implementing role-based authorization is straightforward thanks to its modular design and support for decorators.

What is Role-Based Authorization?


Role-based authorization assigns permissions to users based on their roles. Common roles include “admin,” “user,” and “guest.” Each role has a predefined set of actions it can perform. For example:

  • Admin: Can manage all resources.
  • User: Can read and update their own data.
  • Guest: Can only view public resources.

By implementing role-based authorization, you can easily control access within your application.

Setting Up Role-Based Authorization in NestJS


Here’s how you can implement role-based authorization in NestJS:

1. Install Dependencies


First, ensure you have a NestJS project set up. If not, you can create one using the CLI:


npm i -g @nestjs/cli
nest new my-app

Next, install @nestjs/passport and passport for authentication support:


npm install @nestjs/passport passport passport-jwt
npm install --save-dev @types/passport-jwt
2. Define Roles


Create a roles.enum.ts file to define roles as an enum:


export enum Role {
Admin = 'admin',
User = 'user',
Guest = 'guest',
}
3. Create a Roles Guard


Guards in NestJS intercept requests before they reach route handlers. Create a custom guard to enforce role-based access control.


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

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

canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<Role[]>('roles', context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
return roles.some((role) => user?.roles?.includes(role));
}
}
4. Create a Roles Decorator


To simplify the process of adding roles to route handlers, create a custom decorator:


import { SetMetadata } from '@nestjs/common';
import { Role } from './roles.enum';

export const Roles = (...roles: Role[]) => SetMetadata('roles', roles);
5. Apply the Roles Guard Globally or Locally


To make the RolesGuard active, you can apply it globally or locally. For global application, add it to your AppModule:


import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { RolesGuard } from './roles.guard';

@Module({
providers: [
{
provide: APP_GUARD,
useClass: RolesGuard,
},
],
})
export class AppModule {}

For local application, use it in specific controllers or methods:


import { Controller, Get, UseGuards } from '@nestjs/common';
import { Roles } from './roles.decorator';
import { RolesGuard } from './roles.guard';
import { Role } from './roles.enum';

@Controller('resources')
@UseGuards(RolesGuard)
export class ResourcesController {
@Get()
@Roles(Role.Admin, Role.User)
findAll() {
return 'This endpoint is accessible to Admins and Users.';
}
}
6. Authenticate Users


To identify a user’s roles, ensure your authentication process adds the roles to the user object in the request. This often involves decoding a JWT or using a session store.

Example Authentication Middleware


import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class AuthMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
const token = req.headers['authorization'];
if (token) {
const decoded = this.decodeToken(token); // Implement JWT decoding
req.user = decoded;
}
next();
}

private decodeToken(token: string): any {
// Logic to decode JWT and retrieve user data
return { roles: ['user'] }; // Example decoded payload
}
}
Testing the Implementation


Start your application and test endpoints with users of different roles. Ensure each user can access only what their role permits.

Example Requests

  • Admin User: Should access all routes.
  • Regular User: Should access user-specific routes.
  • Guest: Should be restricted to public routes.
Conclusion


Role-based authorization in NestJS is clean and efficient thanks to decorators, guards, and the framework’s modularity. By following the steps above, you can secure your application while maintaining flexibility and scalability.

For more complex scenarios, consider integrating with external libraries like Casl or implementing attribute-based access control (ABAC).

Читать далее...
 
Назад
Сверху Снизу