Software Development

How to Implement Authentication and Authorization in Nest.js

Blog bannerBlog banner

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.

Authentication vs. Authorization

Before we dive into Nest.js specifics, it's essential to understand the distinction between authentication and authorization:

  • Authentication: Authentication is the process of verifying the identity of a user, ensuring that they are who they claim to be. Common authentication methods include username and password, JSON Web Tokens (JWT), OAuth, and more.
  • Authorization: Authorization comes after authentication and determines what actions a user is allowed to perform once their identity is confirmed. It involves checking permissions and roles to ensure users have the necessary access rights.

Nest.js at a Glance

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.

Authentication Strategies

  • Passport.js: Passport.js is a popular authentication middleware for Node.js that can be seamlessly integrated into Nest.js. It supports a wide range of authentication strategies, including local (username and password), JWT, OAuth2, and more. You can create custom Passport.js strategies to fit your specific authentication needs.

Example:

Code

    // 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 {   
    //Implement your authentication logic here  
    }
    }
            
            
  • Custom Middleware: This approach provides complete flexibility to implement your authentication logic without relying on third-party libraries.

Example: 

Code

    // 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: 

Code

     // 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 
        }
    }         
            
  • Third-Party Identity Providers: If your application relies on third-party identity providers like Google, Facebook, or GitHub for authentication, you can use libraries like passport-google-oauth20, passport-facebook, or passport-github to integrate with these providers.
  • JSON Web Tokens (JWT): Implementing JWT-based authentication is a common choice for building stateless APIs. You can use libraries like jsonwebtoken to generate and verify JWT tokens in Nest.js.

Example: 

import * as jwt from 'jsonwebtoken';

const token = jwt.sign({ userId: user.id }, 'secretKey', { expiresIn: '1h' });

Authorization Strategies

  • Guarding Routes: Nest.js provides guards that can be used to protect routes or endpoints. You can define custom guards to implement authorization logic. Common guards include AuthGuard, RolesGuard, and JwtAuthGuard.
  • Role-Based Authorization: Implement role-based authorization by assigning roles to users and then using guards to check if a user has the required role to access specific resources.

Example: 

Code

    // 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 

Code

    // 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  
        }
    }                             
            
  • Attribute-Based Authorization: This approach involves attaching permissions or attributes to resources and users. You can then create custom guards to check if a user has the necessary attributes to access a resource.

Example:

Code

    // 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 

Code

    // 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  
        }
    }                                                            
            
  • Policy-Based Authorization: Implement policies that define rules for resource access. You can create custom policies and use them in guards to determine if a user is authorized to perform a specific action.

Example: 

Code

    // 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

Code

    // 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 

Code

    // 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 
        }
    }                                                                                                           
            

Conclusion

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.

expand our team
card user img
Twitter iconLinked icon

Zignuts Technolab delivers future-ready tech solutions and keeps you updated with the latest innovations through our blogs. Read, learn, and share!

Let’s Connect

Exclusive Free Consultation

Valid number
Claim My Spot!
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
download ready
Thank You
Your submission has been received.
We will be in touch and contact you soon!

Our Latest Blogs

Load More

Our Latest Blogs

View All Blogs