Delving Developer

Implement JWT Authentication in NestJS

Eddie Cunningham
Eddie Cunningham
4 min readNestJS
Cover Image for Implement JWT Authentication in NestJS

NestJS, a progressive Node.js framework, is renowned for its robust architecture and scalability. When it comes to securing web applications, authentication and authorization are critical aspects. In this article, we will delve into how to implement JSON Web Tokens (JWT) for authentication and authorization in a NestJS application, ensuring your application remains secure while providing a seamless user experience.

Understanding Authentication and Authorization

Before diving into NestJS specifics, it's crucial to differentiate between authentication and authorization. Authentication is the process of verifying the identity of a user, while authorization determines what resources or actions a user has access to. Together, they form a comprehensive security solution for web applications.

What is JWT?

JSON Web Tokens (JWT) are an open standard (RFC 7519) used to securely transmit information between parties as a JSON object. They are compact, self-contained, and can be used for authentication and information exchange. A typical JWT consists of three parts: a header, a payload, and a signature, encoded as a base64 string.

  • Header: Contains the algorithm and token type.
  • Payload: Contains claims, which are statements about an entity and additional metadata.
  • Signature: Verifies the sender of the JWT and ensures the message wasn't altered.

Setting Up a NestJS Application

To begin, ensure you have NestJS CLI installed and create a new NestJS project:

npm i -g @nestjs/cli
nest new my-nestjs-app

Navigate to your project directory:

cd my-nestjs-app

Installing Necessary Packages

For JWT authentication, we'll need to install the following packages:

  • @nestjs/jwt: Provides JWT utilities.
  • passport-jwt: A Passport strategy for handling JWTs.
  • passport: Middleware for Node.js that simplifies authentication.

Install the packages with:

npm install @nestjs/jwt passport passport-jwt

Implementing JWT Authentication

  1. Creating the Authentication Module

First, generate an auth module:

nest generate module auth
  1. Creating the AuthService

Generate a service within the auth module for handling authentication logic:

nest generate service auth

Within auth.service.ts, write a function to validate the user's credentials and return a JWT:

import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';

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

  async validateUser(username: string, password: string): Promise<any> {
    // Simulated user validation logic
    if (username === 'test' && password === 'test123') {
      return { username };
    }
    return null;
  }

  async login(user: any) {
    const payload = { username: user.username };
    return {
      access_token: this.jwtService.sign(payload),
    };
  }
}
  1. Setting Up JWT Strategy

Create a JWT strategy to handle token verification. Generate a new file jwt.strategy.ts in the auth folder:

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

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

  async validate(payload: any) {
    return { username: payload.username };
  }
}
  1. Integrating JWT in the Auth Module

Update the auth.module.ts to include the JWT and Passport strategies:

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

@Module({
  imports: [
    PassportModule,
    JwtModule.register({
      secret: 'secretKey',
      signOptions: { expiresIn: '60s' },
    }),
  ],
  providers: [AuthService, JwtStrategy],
  exports: [AuthService],
})
export class AuthModule {}

Applying Authentication Guards

Now, protect specific routes using NestJS guards. Create a jwt-auth.guard.ts file:

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

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

Apply this guard to routes that require authentication:

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

@Controller('profile')
export class ProfileController {
  @UseGuards(JwtAuthGuard)
  @Get()
  getProfile() {
    return {
      message: 'This is a protected route',
    };
  }
}

Conclusion

In conclusion, JWT is a powerful way to handle authentication and authorization in your NestJS applications. It provides a scalable and efficient means to secure APIs. By understanding the mechanics of JWTs and integrating them with NestJS's powerful tools, you can ensure your applications remain secure and performant.

For further reading on JWTs, consider exploring MDN's documentation on JSON Web Tokens to gain deeper insights into their usage and benefits.