integrating-jwt-authentication-in-a-nestjs-application-for-secure-access.html

Integrating JWT Authentication in a NestJS Application for Secure Access

In today's digital landscape, ensuring secure access to your applications is paramount. One effective way to achieve this is through JWT (JSON Web Token) authentication. NestJS, a progressive Node.js framework for building efficient server-side applications, offers a robust environment for implementing JWT-based authentication. In this article, we will dive deep into integrating JWT authentication in a NestJS application, exploring its definitions, use cases, and providing step-by-step coding examples.

What is JWT Authentication?

JWT, or JSON Web Token, is a compact, URL-safe means of representing claims to be transferred between two parties. These claims are encoded as a JSON object and can be used for various purposes, such as authentication and information exchange. The primary advantage of JWT is its stateless nature, meaning that the server does not need to store session data, making it a scalable solution for user authentication.

Key Features of JWT

  • Compact: Can be sent via URL, POST parameter, or inside an HTTP header.
  • Self-contained: Contains all the necessary information about the user, reducing database queries.
  • Stateless: No need for server-side sessions, improving scalability.

Use Cases of JWT Authentication

JWT is commonly used in several scenarios, including:

  • Single Page Applications (SPAs): Where the frontend and backend are decoupled.
  • Mobile Applications: Allowing secure access to APIs.
  • Microservices: Facilitating communication between independent services.

Setting Up a NestJS Application with JWT Authentication

Now, let’s dive into the practical side. We will build a simple NestJS application that incorporates JWT authentication. Here’s a step-by-step guide to get you started.

Step 1: Create a New NestJS Project

First, ensure you have Node.js and Nest CLI installed. If not, install them using the following commands:

npm install -g @nestjs/cli

Then, create a new NestJS project:

nestjs new jwt-auth-example
cd jwt-auth-example

Step 2: Install Required Packages

Next, install the necessary packages for JWT authentication:

npm install @nestjs/jwt @nestjs/passport passport passport-jwt bcryptjs

This command installs the JWT module, Passport for authentication, and bcrypt for password hashing.

Step 3: Create the User Module

Generate a user module where we will handle user-related functionalities:

nestjs generate module users
nestjs generate service users
nestjs generate controller users

Step 4: Implement User Registration and Login

In the users.service.ts, implement methods for user registration and login.

import { Injectable } from '@nestjs/common';
import { User } from './user.entity'; // Assume User entity is defined
import * as bcrypt from 'bcryptjs';

@Injectable()
export class UsersService {
  private users: User[] = []; // In-memory storage for simplicity

  async register(username: string, password: string): Promise<User> {
    const hashedPassword = await bcrypt.hash(password, 10);
    const newUser = { username, password: hashedPassword };
    this.users.push(newUser);
    return newUser;
  }

  async findUser(username: string): Promise<User | undefined> {
    return this.users.find(user => user.username === username);
  }
}

Step 5: Create the JWT Strategy

Create a JWT strategy to handle authentication. Generate a new strategy file:

nestjs generate service auth

In auth.service.ts, implement the strategy:

import { Injectable } from '@nestjs/common';
import { JwtStrategy } from '@nestjs/jwt';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt } from 'passport-jwt';
import { UsersService } from '../users/users.service';

@Injectable()
export class AuthService extends PassportStrategy(JwtStrategy) {
  constructor(private usersService: UsersService) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: process.env.JWT_SECRET,
    });
  }

  async validate(payload: any) {
    return await this.usersService.findUser(payload.username);
  }
}

Step 6: Create JWT Authentication Controller

Create a controller to handle registration and login routes.

import { Controller, Post, Body } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { UsersService } from './users.service';

@Controller('auth')
export class AuthController {
  constructor(private usersService: UsersService, private jwtService: JwtService) {}

  @Post('register')
  async register(@Body() body: { username: string; password: string }) {
    return this.usersService.register(body.username, body.password);
  }

  @Post('login')
  async login(@Body() body: { username: string; password: string }) {
    const user = await this.usersService.findUser(body.username);
    if (user && await bcrypt.compare(body.password, user.password)) {
      const payload = { username: user.username };
      return {
        access_token: this.jwtService.sign(payload),
      };
    }
    throw new UnauthorizedException();
  }
}

Step 7: Configure JWT Module

Finally, configure the JWT module in your main application module (app.module.ts):

import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthController } from './auth/auth.controller';
import { AuthService } from './auth/auth.service';
import { UsersModule } from './users/users.module';

@Module({
  imports: [
    UsersModule,
    JwtModule.register({
      secret: process.env.JWT_SECRET || 'defaultSecret',
      signOptions: { expiresIn: '60s' },
    }),
  ],
  controllers: [AuthController],
  providers: [AuthService],
})
export class AppModule {}

Step 8: Protect Routes with JWT

To secure specific routes, use the @UseGuards() decorator with JWT:

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

@Controller('protected')
export class ProtectedController {
  @UseGuards(AuthGuard('jwt'))
  @Get()
  getProtectedResource() {
    return { message: 'This is a protected resource' };
  }
}

Conclusion

By following the steps outlined in this article, you have successfully integrated JWT authentication into your NestJS application. You learned how to create user registration and login functionality, implement JWT strategies, and protect routes effectively.

Quick Recap

  • JWT is a secure and scalable way to handle authentication.
  • NestJS provides powerful modules and decorators to simplify implementation.
  • Always hash passwords and manage secrets securely.

With this knowledge, you are now equipped to enhance your application’s security and usability through JWT authentication in NestJS. Happy coding!

SR
Syed
Rizwan

About the Author

Syed Rizwan is a Machine Learning Engineer with 5 years of experience in AI, IoT, and Industrial Automation.