10-setting-up-jwt-authentication-in-a-nestjs-application-with-typescript.html

Setting Up JWT Authentication in a NestJS Application with TypeScript

In the modern web development landscape, securing your applications is more crucial than ever. JSON Web Tokens (JWT) have become a popular method for handling authentication, especially in APIs. In this article, we’ll explore how to set up JWT authentication in a NestJS application using TypeScript. Whether you're building a small project or a large-scale application, understanding JWT can significantly enhance your app’s security.

What is JWT?

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, allowing the claims to be digitally signed or integrity protected with a message authentication code (MAC) and/or encrypted.

Use Cases for JWT

  • Authentication: The most common use case, where JWTs are issued after a user logs in.
  • Information Exchange: JWTs can be used to securely transmit information between parties.
  • Single Sign-On (SSO): JWT allows users to log in once and gain access to multiple applications.

Prerequisites

Before we dive into the implementation, ensure you have the following:

  • Node.js installed (preferably the latest LTS version).
  • A basic understanding of TypeScript and NestJS.
  • NestJS CLI installed globally. If not, you can install it using:
npm install -g @nestjs/cli

Step-by-Step Guide to Implementing JWT Authentication

Step 1: Create a New NestJS Application

Start by creating a new NestJS project:

nest new jwt-auth-example
cd jwt-auth-example

Step 2: Install Required Dependencies

You’ll need several packages to handle JWT authentication:

npm install @nestjs/jwt @nestjs/passport passport passport-jwt bcryptjs
npm install --save-dev @types/passport-jwt @types/bcryptjs

Step 3: Create the Auth Module

Next, generate the authentication module and service:

nest g module auth
nest g service auth
nest g controller auth

Step 4: Configure JWT Strategy

In the auth folder, create a new file called jwt.strategy.ts. This file will configure the JWT strategy for Passport:

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { AuthService } from './auth.service';
import { JwtPayload } from './jwt-payload.interface';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(private readonly authService: AuthService) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: 'your_secret_key', // Replace with your secret
    });
  }

  async validate(payload: JwtPayload) {
    return await this.authService.validateUser(payload);
  }
}

Step 5: Implement the Auth Service

In the auth.service.ts, implement the method to validate users and generate JWTs:

import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { User } from './user.entity'; // Assume you have a User entity
import { JwtPayload } from './jwt-payload.interface';

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

  async validateUser(payload: JwtPayload): Promise<User> {
    // Implement your user validation logic here
    // Example: Find user by ID in the database
    return await this.findUserById(payload.id);
  }

  async login(user: User) {
    const payload: JwtPayload = { id: user.id };
    return {
      access_token: this.jwtService.sign(payload),
    };
  }
}

Step 6: Create the Auth Controller

In the auth.controller.ts, set up routes for login:

import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';
import { User } from './user.entity'; // Assume User entity is defined

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

  @Post('login')
  async login(@Body() user: User) {
    return this.authService.login(user);
  }
}

Step 7: Set Up JWT Module

In your auth.module.ts, import the necessary modules:

import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { JwtStrategy } from './jwt.strategy';

@Module({
  imports: [
    JwtModule.register({
      secret: 'your_secret_key', // Replace with your secret
      signOptions: { expiresIn: '60s' }, // Token expiration time
    }),
  ],
  providers: [AuthService, JwtStrategy],
  controllers: [AuthController],
})
export class AuthModule {}

Step 8: Protecting Routes

To protect routes in your application, you can use the @UseGuards decorator from NestJS. For example:

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

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

Conclusion

By following these steps, you have successfully set up JWT authentication in your NestJS application using TypeScript. JWT provides a secure way to handle user authentication and authorization, ensuring that your application is safe from unauthorized access.

Key Takeaways

  • JWT is a compact way to securely transmit information between parties.
  • NestJS provides excellent support for implementing JWT authentication through modules and decorators.
  • Always protect sensitive routes using guards to enhance security.

With this foundational knowledge, you can now expand your NestJS application, integrate more complex authentication and authorization mechanisms, and build robust APIs. 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.