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
- What is Passport.js and Why Use It?
- Strategy Overview
- Local Strategy: Email and Password Login
- JWT Strategy: Stateless Authentication
- OAuth2 Strategy: Third-Party Authentication
- Google Strategy: Social Login with Google
- Best Practices
- 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
Strategy | Purpose | Use Case |
---|---|---|
Local | Username/email + password login | Traditional login systems |
JWT | Token-based stateless auth | API token authentication |
OAuth2 | Third-party authentication | Login with GitHub, Google, etc. |
Specialized OAuth2 for Google | Google 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.