(NestJS-10) Role-Based Authorization in NestJS π
In modern web applications, securing access to resources is crucial. One effective way to do this is through Role-Based Authorization. This article will guide you through implementing role-based authorization in a NestJS application, ensuring that only users with specific roles can access certain routes.
This builds on the authentication mechanism covered in the previous article, where we implemented JWT-based authentication.
Prerequisites
Before we begin, ensure the following are set up:
- NestJS Project: An existing NestJS project with authentication configured.
- Entities: A
User
entity with arole
column. - JWT Authentication: JWT strategy implemented for user authentication.
Understanding Role-Based Authorization
Role-Based Authorization (RBAC) restricts access to resources based on assigned user roles. This ensures that only authorized users can perform specific actions.
For example:
- Admin users may have full access to manage users and resources.
- Moderators may be limited to managing specific content.
- Regular Users may only access their own data.
We achieve this by using custom decorators and guards to protect our routes.
Implementing Role-Based Authorization in NestJS
1. Creating a Role Guard
NestJS guards allow us to control access to routes. We will create a RolesGuard
to check whether the user has the required role for a route.
π Create a new file roles.guard.ts
:
// auth/roles.guard.ts
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 skipGuard = this.reflector.get<boolean>('skipAuthGuard', context.getHandler());
if (skipGuard) {
return true;
}
const roles = this.reflector.get<string[]>('roles', context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
return roles.some((role) => user.role == role);
}
}
How This Works
- Retrieves roles from the route metadata.
- Extracts the authenticated user from the request.
- Checks if the userβs role matches any of the required roles.
2. Creating a Custom Decorator
To simplify applying role-based restrictions, we create a custom decorator to set metadata on routes.
π Create a new file roles.decorator.ts
:
// auth/roles.decorator.ts
import { SetMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
3. Apply the Role Guard Globally
Update your AppModule
to include the RolesGuard
.
π Modify auth.module.ts
import { RolesGuard } from './role.guard';
import { APP_GUARD } from '@nestjs/core';
@Module({
providers: [
{
provide: APP_GUARD,
useClass: RolesGuard,
},
]
})
export class AuthModule { }
This ensures that role-based authorization applies to all routes by default.
4. Securing Routes
Use the @Roles()
decorator to secure your routes.
π Example Usage in users.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { Roles } from '../auth/roles.decorator';
import { RoleEnum } from '../enums/role.enum';
import { UserService } from './user.service';
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get(':id')
@Roles(RoleEnum.ADMIN, RoleEnum.SELLER)
async findOne(@Param('id') id: string) {
return this.userService.findOne(id);
}
}
By applying the @Roles()
decorator at the method level, you ensure that specific endpoints can have different access rules.
Conclusion
In this article, we have seen how to implement Role-Based Access Control (RBAC) in a NestJS application. We covered:
- Creating a Role Guard to restrict access to routes.
- Implementing a custom decorator to apply role-based restrictions.
- Applying the RolesGuard globally.
- Securing routes with role-based permissions.
RBAC is a powerful way to manage permissions and access control in your application, making it easier to manage user access to different parts of your system.
Next Steps
In our next article, we will explore Global Exception Filter, covering advanced strategies.
GitHub Repository:
You can find the complete code for this implementation on GitHub: bhargavachary123
Support & Contribution If you liked this article, please consider supporting me through Buy Me a Coffee.
If you found this article useful, leave a clap (π) and a comment. Happy coding! βοΈ