Setting Up OAuth 2.0 Authentication in a NestJS Application
In today’s digital landscape, securing your applications is more crucial than ever. OAuth 2.0 has become the standard for granting third-party applications limited access to a user’s resources without exposing their credentials. If you're developing a NestJS application, integrating OAuth 2.0 can enhance your security and user experience. This article will guide you through the process of setting up OAuth 2.0 authentication in a NestJS application, providing clear code examples and actionable insights to help you along the way.
What is OAuth 2.0?
OAuth 2.0 is an authorization framework that enables applications to obtain limited access to user accounts on an HTTP service. It allows users to grant access to their resources on one site to another site without sharing their credentials. Common use cases include:
- Social Login: Allowing users to log in using their Google or Facebook accounts.
- API Access: Providing third-party apps access to user data securely.
- Delegated Permissions: Allowing users to grant specific permissions to different applications.
Getting Started with NestJS
NestJS is a progressive Node.js framework for building efficient and scalable server-side applications. It leverages TypeScript and supports modular architecture, making it an excellent choice for implementing OAuth 2.0.
Prerequisites
Before diving into implementation, ensure you have the following:
- Node.js installed (version 12 or above).
- NestJS CLI installed globally. You can install it using:
bash npm install -g @nestjs/cli
- A NestJS application set up. You can create one using:
bash nest new oauth-nestjs
Step 1: Install Required Packages
To set up OAuth 2.0 in your NestJS application, you need several packages. Install them using npm:
npm install @nestjs/passport passport passport-google-oauth20 express-session
Step 2: Create the Authentication Module
Create a new module for authentication:
nest generate module auth
Next, create an authentication service and controller:
nest generate service auth/auth
nest generate controller auth/auth
Step 3: Configure the Passport Strategy
In the auth
module, configure the Google OAuth strategy. Create a new file google.strategy.ts
in the auth
folder.
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-google-oauth20';
import { AuthService } from './auth.service';
@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor(private readonly authService: AuthService) {
super({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: 'http://localhost:3000/auth/google/callback',
scope: ['profile', 'email'],
});
}
async validate(accessToken: string, refreshToken: string, profile: any) {
const user = await this.authService.validateUser(profile);
return user;
}
}
Step 4: Implement the Authentication Logic
In your auth.service.ts
, implement the logic to validate users:
import { Injectable } from '@nestjs/common';
@Injectable()
export class AuthService {
async validateUser(profile: any): Promise<any> {
// Here, you would typically find or create a user in your database
return {
id: profile.id,
email: profile.emails[0].value,
name: profile.displayName,
};
}
}
Step 5: Set Up Routes and Session Management
In your auth.controller.ts
, set up routes for handling authentication:
import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Request, Response } from 'express';
@Controller('auth')
export class AuthController {
@Get('google')
@UseGuards(AuthGuard('google'))
async googleLogin(@Req() req: Request) {
// Initiates the Google OAuth flow
}
@Get('google/callback')
@UseGuards(AuthGuard('google'))
googleLoginCallback(@Req() req: Request, @Res() res: Response) {
// Successful authentication, redirect or respond with user data
res.redirect('http://localhost:3000/dashboard'); // Redirect to your dashboard
}
}
Step 6: Configure Session Management
To manage user sessions, configure session middleware in your main application file (main.ts
):
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as session from 'express-session';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(
session({
secret: 'your_secret_key',
resave: false,
saveUninitialized: false,
}),
);
await app.listen(3000);
}
bootstrap();
Step 7: Environment Variables
Create a .env
file at the root of your project to store sensitive information:
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
Make sure to replace your_google_client_id
and your_google_client_secret
with your actual credentials from Google Developer Console.
Step 8: Testing the Setup
Now that everything is set up, run your NestJS application:
npm run start
Visit http://localhost:3000/auth/google
to initiate the OAuth flow. Upon successful login, you will be redirected to your dashboard.
Troubleshooting Common Issues
- Invalid Credentials: Ensure that your Google OAuth client ID and secret are set correctly in the
.env
file. - Callback URL Mismatch: Verify that your callback URL matches the one registered in the Google Developer Console.
- Session Issues: Ensure that session middleware is correctly configured in the main application file.
Conclusion
Setting up OAuth 2.0 authentication in a NestJS application can significantly enhance your user experience and security. By following the steps outlined in this article, you can integrate Google authentication seamlessly. As you expand your application, consider adding more strategies or customizing user roles to fit your needs. Happy coding!