Passport Strategies in NestJS: JWT, Local, OAuth2, and Google Login

NestJS integrates seamlessly with Passport.js, a popular Node.js middleware for authentication. Passport provides a rich ecosystem of strategies that you can plug into your app, including Local, JWT, OAuth2, and providers like Google, Facebook, and more.

In this module, you’ll learn how to implement and integrate various Passport strategies in NestJS, with a focus on JWT, Local, OAuth2, and Google authentication.


Table of Contents

  1. What is Passport.js and Why Use It?
  2. Strategy Overview
  3. Local Strategy: Email and Password Login
  4. JWT Strategy: Stateless Authentication
  5. OAuth2 Strategy: Third-Party Authentication
  6. Google Strategy: Social Login with Google
  7. Best Practices
  8. Conclusion

What is Passport.js and Why Use It?

Passport.js is a flexible authentication library for Node.js that supports a wide variety of authentication mechanisms via strategies. NestJS leverages Passport under the hood, providing decorators, guards, and modules to use these strategies in a structured way.


Strategy Overview

StrategyPurposeUse Case
LocalUsername/email + password loginTraditional login systems
JWTToken-based stateless authAPI token authentication
OAuth2Third-party authenticationLogin with GitHub, Google, etc.
GoogleSpecialized OAuth2 for GoogleGoogle login integration

Local Strategy: Email and Password Login

This strategy is used to authenticate a user with credentials stored in your database.

Install Packages

bashCopyEditnpm install passport passport-local
npm install --save-dev @types/passport-local

Create the Strategy

tsCopyEdit// local.strategy.ts
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({ usernameField: 'email' });
  }

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

Create Local Auth Guard

tsCopyEdit// local-auth.guard.ts
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {}

Use It in Controller

tsCopyEdit@Post('login')
@UseGuards(LocalAuthGuard)
async login(@Request() req) {
  return this.authService.login(req.user); // issue JWT
}

JWT Strategy: Stateless Authentication

We’ve already covered JWT in the previous module. It issues a token after login and uses it for subsequent requests.

Here’s a quick reminder of the guard:

tsCopyEdit@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

JWT Strategy uses the token to verify and validate users without storing session data on the server.


OAuth2 Strategy: Third-Party Authentication

NestJS does not officially support generic OAuth2, but you can easily use it with Passport’s strategy base.

Install Required Packages

bashCopyEditnpm install passport-oauth2
npm install --save-dev @types/passport-oauth2

Then implement a custom strategy using PassportStrategy from @nestjs/passport and configure it with your provider’s client ID, secret, and callback URL.

Due to provider-specific configurations, it’s often better to use a dedicated strategy like passport-google-oauth20.


Google Strategy: Social Login with Google

This is one of the most commonly used OAuth2 strategies.

Install Google Strategy

bashCopyEditnpm install passport-google-oauth20
npm install --save-dev @types/passport-google-oauth20

Configure the Strategy

tsCopyEdit// google.strategy.ts
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, VerifyCallback } from 'passport-google-oauth20';
import { Injectable } from '@nestjs/common';

@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
  constructor() {
    super({
      clientID: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      callbackURL: 'http://localhost:3000/auth/google/redirect',
      scope: ['email', 'profile'],
    });
  }

  async validate(accessToken: string, refreshToken: string, profile: any, done: VerifyCallback): Promise<any> {
    const { name, emails } = profile;
    const user = {
      email: emails[0].value,
      name: name.givenName,
      accessToken,
    };
    done(null, user);
  }
}

Add Redirect Handlers

tsCopyEdit// auth.controller.ts
@Get('google')
@UseGuards(AuthGuard('google'))
async googleAuth() {
  // initiates Google OAuth2 login flow
}

@Get('google/redirect')
@UseGuards(AuthGuard('google'))
googleAuthRedirect(@Request() req) {
  return this.authService.loginWithGoogle(req.user);
}

Make sure to configure Google OAuth in the Google Developer Console and add your redirect URL.


Best Practices

  • Store secrets securely using environment variables.
  • Validate user identity on first login from external providers (e.g., link to existing user).
  • Use JWT with social login to keep a unified session management strategy.
  • Rate limit login endpoints to prevent brute force attacks.
  • Keep strategies modularized to separate logic and responsibilities.

Conclusion

NestJS and Passport together offer a flexible and robust authentication solution for any type of application. By combining Local, JWT, and OAuth2 strategies like Google login, you can provide secure and convenient authentication methods tailored to your users.