DEV Community

Wakeup Flower
Wakeup Flower

Posted on

NestJS Passport Strategies

Strategy Use Case Strategy Name
local Username/password login 'local'
jwt Token-based auth 'jwt'
google OAuth login with Google 'google'
facebook OAuth login with Facebook 'facebook'
github OAuth login with GitHub 'github'
linkedin OAuth login with LinkedIn 'linkedin'
azure-ad SAML or OIDC with Azure AD 'azure-ad'
saml Enterprise SSO 'saml'
anonymous (custom) Guest users 'anonymous'
2fa (custom) Multi-factor authentication '2fa'

This allows you to use different strategies on different routes — for example:

/auth/login uses 'local'

/auth/google uses 'google'

/admin/* routes use 'jwt' with admin role checks

nest g resource auth

  • with entities, but without test nest g resource auth --no-spec --type=rest

Example 1: Basic Local Strategy (No users)

// local.strategy.ts
import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super(); // expects 'username' and 'password' in body by default
  }

  async validate(username: string, password: string): Promise<any> {
    // Normally you'd validate against DB here
    if (username === 'admin' && password === '1234') {
      return { username };
    }
    return null;
  }
}


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

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


// auth.controller.ts
import { Controller, Post, Req, UseGuards } from '@nestjs/common';
import { LocalAuthGuard } from './local-auth.guard';

@Controller('auth')
export class AuthController {
  @UseGuards(LocalAuthGuard)
  @Post('login')
  async login(@Req() req) {
    return req.user;
  }
}

// auth.module.ts
import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { LocalStrategy } from './local.strategy';
import { AuthController } from './auth.controller';

@Module({
  imports: [PassportModule],
  providers: [LocalStrategy],
  controllers: [AuthController],
})
export class AuthModule {}

Enter fullscreen mode Exit fullscreen mode

Example 2: Add JWT for Token-based Authentication

// jwt.strategy.ts
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, ExtractJwt } from 'passport-jwt';
import { Injectable } from '@nestjs/common';

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

  async validate(payload: any) {
    return { userId: payload.sub, username: payload.username };
  }
}


// auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(private jwtService: JwtService) {}

  async login(user: any) {
    const payload = { username: user.username, sub: user.userId };
    return {
      access_token: this.jwtService.sign(payload),
    };
  }
}

// auth.controller.ts
import { Controller, Post, Req, UseGuards } from '@nestjs/common';
import { LocalAuthGuard } from './local-auth.guard';
import { AuthService } from './auth.service';

@Controller('auth')
export class AuthController {
  constructor(private authService: AuthService) {}

  @UseGuards(LocalAuthGuard)
  @Post('login')
  async login(@Req() req) {
    return this.authService.login(req.user);
  }
}

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

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

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

@Controller('profile')
export class ProfileController {
  @UseGuards(JwtAuthGuard)
  @Get()
  getProfile() {
    return { message: 'You are authenticated!' };
  }
}

Enter fullscreen mode Exit fullscreen mode

Example 3 Google OAuth with Jwt

Go to https://console.cloud.google.com/apis/credentials:

Create a project and OAuth client ID.

Set redirect URI: http://localhost:3000/auth/google/redirect

Choose Web Application as the client type.

If you want to issue your own JWTs after Google auth, you can:

Generate a JWT in the googleAuthRedirect handler.

Store or register users in a database at that point.

npm install @nestjs/passport passport passport-google-oauth20
npm install @nestjs/jwt passport-jwt --save

//google.strategy.ts

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

@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, photos } = profile;
    const user = {
      email: emails[0].value,
      firstName: name.givenName,
      lastName: name.familyName,
      picture: photos[0].value,
      accessToken,
    };
    done(null, user);
  }
}


//auth.controller.ts

import { Controller, Get, Req, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Controller('auth')
export class AuthController {
  @Get('google')
  @UseGuards(AuthGuard('google'))
  async googleAuth() {
    // initiates the Google OAuth2 login flow
  }

  @Get('google/redirect')
  @UseGuards(AuthGuard('google'))
  googleAuthRedirect(@Req() req) {
    // handle the Google OAuth2 callback
    return {
      message: 'User Info from Google',
      user: req.user,
    };
  }
}

//auth.module.ts
import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { AuthController } from './auth.controller';
import { GoogleStrategy } from './google.strategy';

@Module({
  imports: [PassportModule],
  controllers: [AuthController],
  providers: [GoogleStrategy],
})
export class AuthModule {}

//.env
GOOGLE_CLIENT_ID=xxx
GOOGLE_CLIENT_SECRET=xxx


Enter fullscreen mode Exit fullscreen mode

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.