How to Use Passport.js in NestJS

Updated: December 31, 2023 By: Guest Contributor Post a comment

Integrating Passport.js for authentication in a NestJS application provides robust security features with flexibility and modularity.

Setting Up a New NestJS Project

Before diving into Passport.js, create a new NestJS application:

npm i -g @nestjs/cli
nestjs new auth-project

Move into your new project directory:

cd auth-project

Installing Passport.js and Necessary Modules

Begin by installing Passport, the NestJS Passport module, and a strategy, such as Passport-Local:

npm install passport @nestjs/passport passport-local
npm install -D @types/passport-local

Creating Auth Module and Service

Create an Auth module and service within NestJS:

nest g module auth
nest g service auth

Setting Up Passport Local Strategy

In your auth.service.ts, set up the validateUser method:

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

@Injectable()
export class AuthService {
  async validateUser(username: string, pass: string): Promise {
    // User validation logic
  }
}

Create a local.strategy.ts using NestJS decorators that integrate Passport’s local strategy:

import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthService } from './auth.service';

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super();
  }

  async validate(username: string, password: string): Promise {
    const user = await this.authService.validateUser(username, password);
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}

Implementing Authentication in the Controller

Add authentication routes to your auth.controller.ts, applying auth guard:

import { Controller, Post, Request, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Controller('auth')
export class AuthController {
  @UseGuards(AuthGuard('local'))
  @Post('login')
  async login(@Request() req) {
    // Passport automatically adds user to the request
    return req.user;
  }
}

Authenticating Using JWTs

For JWT-based authentication, install additional dependencies and create a JWT strategy:

npm install @nestjs/jwt passport-jwt
npm install -D @types/passport-jwt

Create a jwt.strategy.ts file:

import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { AuthService } from './auth.service';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: 'secretkey',
    });
  }

  async validate(payload: any) {
    // Validate token payload and return user data
  }
}

Securing NestJS Endpoints

Use the @UseGuards decorator with the AuthGuard to protect endpoints. Here’s an example with JWT:

import { Controller, Get, UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from './jwt-auth.guard';

@Controller('profile')
export class ProfileController {
  @UseGuards(JwtAuthGuard)
  @Get()
  getProfile(@Request() req) {
    return req.user;
  }
}

Understanding Sessions and Cookies

Passport can utilize session management and cookies. Implement this as needed using additional middleware and configuration within your NestJS application.

Advanced Passport.js Strategies

Explore third-party strategies like OAuth or OpenID Connect to integrate more complex authentication flows into your application. These strategies are installed and configured similarly but will require additional setup relevant to the chosen provider (e.g., Google, Facebook).

Conclusion

Incorporating Passport.js into NestJS enables you to secure your application effectively. Start with simple strategies and expand your security infrastructure as needed to include more sophisticated authentication methods.