Authentication and authorization are crucial aspects of modern web applications, ensuring that users have the right access to the right resources. In the world of Node.js and TypeScript, Nest.js has emerged as a powerful and popular framework for building scalable and maintainable server-side applications. we'll delve into the concepts of authentication and authorization in Nest.js and how you can implement them in your projects. Secure your Nest.js projects with confidence!
If you are just getting started with nestjs, we recommend checking out this tutorial on how to create and setup nestjs project.
Before we dive into Nest.js specifics, it's essential to understand the distinction between authentication and authorization:
Nest.js is a Node.js framework that leverages TypeScript to simplify the development of scalable and maintainable server-side applications. It's built on top of Express.js, but it also supports other HTTP frameworks like Fastify. Nest.js encourages the use of decorators, modules, and dependency injection to create structured and organized code. Here is the official website of the framework.
Example:
// Import the necessary modules
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local';
// Create a custom authentication strategy
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor() {
super({ usernameField: 'email' });
}
async validate(email: string, password: string): Promise<any> {
// Implement your authentication logic here
}
}
Example:
// custom-auth.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
@Injectable()
export class CustomAuthMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: Function) {
// Implement your custom authentication logic here
const isAuthenticated = /* Check if the user is authenticated */;
if (isAuthenticated) {
next(); // Proceed to the next middleware or route handler
} else {
res.status(403).json({ message: 'Unauthorized' });
}
}
}
Next, you need to apply the custom authentication middleware to
specific routes or globally to your application. You can do this in
your module or controller:
Example:
// app.module.ts
import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { CustomAuthMiddleware } from './custom-auth.middleware';
import { AppController } from './app.controller';
@Module({
controllers: [AppController],
})
export class AppModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(CustomAuthMiddleware)
.exclude({ path: 'public', method: RequestMethod.ALL }) // Exclude public routes
.forRoutes('*'); // Apply middleware to all routes
}
}
Example:
import * as jwt from 'jsonwebtoken';
const token = jwt.sign({ userId: user.id }, 'secretKey', { expiresIn: '1h' });
Example:
// roles.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly requiredRoles: string[]) {}
canActivate(context: ExecutionContext): boolean {
const { user } = context.switchToHttp().getRequest();
// Check if the user has at least one of the required roles
return this.requiredRoles.some(role => user.roles.includes(role));
}
}
AND
// app.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { RolesGuard } from './roles.guard'
@Controller('admin')
export class AdminController {
@Get('resource')
@UseGuards(RolesGuard)
getAdminResource() {
// This route is protected by the RolesGuard
}
}
Example:
// attributes.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
@Injectable()
export class AttributesGuard implements CanActivate {
constructor(private readonly requiredAttributes: string[]) {}
canActivate(context: ExecutionContext): boolean {
const { user, params } = context.switchToHttp().getRequest();
// Check if the user has the necessary attributes to access this resource
return this.requiredAttributes.every(attribute => user.attributes.includes(attribute));
}
}
AND
// app.controller.ts
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
import { AttributesGuard } from './attributes.guard';
@Controller('resources')
export class ResourceController {
@Get(':id')
@UseGuards(AttributesGuard)
getResource(@Param('id') resourceId: string) {
// This route is protected by the AttributesGuard
}
}
Example:
// policies.ts
export class ResourcePolicy {
static canEdit(user, resource) {
return user.id === resource.ownerId;
}
static canDelete(user, resource) {
return user.id === resource.ownerId || user.isAdmin;
}
}
AND
// policies.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { ResourcePolicy } from './policies';
@Injectable()
export class PoliciesGuard implements CanActivate {
constructor(private readonly policyMethod: Function) {}
canActivate(context: ExecutionContext): boolean {
const { user, params } = context.switchToHttp().getRequest();
const resource = /* Fetch the resource based on params */
return this.policyMethod(user, resource);
}
}
AND
// app.controller.ts
import { Controller, Delete, Get, Param, UseGuards } from '@nestjs/common';
import { PoliciesGuard } from './policies.guard';
import { ResourcePolicy } from './policies';
@Controller('resources')
export class ResourceController {
@Delete(':id')
@UseGuards(PoliciesGuard)
deleteResource(@Param('id') resourceId: string) {
// This route is protected by the PoliciesGuard with the ResourcePolicy.canDelete method
}
}
Authentication and authorization are fundamental aspects of building secure and user-friendly web applications. Nest.js simplifies the process of implementing these mechanisms with its modular and structured approach, making it an excellent choice for building robust server-side applications. By understanding and effectively using authentication strategies, guards, and decorators, you can ensure that your Nest.js application is both secure and accessible to authorized users.
Portfolio
Recent
Projects
Explore Projects