creating-a-secure-rest-api-with-nestjs-and-jwt-authentication.html

Creating a Secure REST API with NestJS and JWT Authentication

In today's digital landscape, APIs play a crucial role in enabling communication between different software systems. One popular framework for building robust APIs in Node.js is NestJS. NestJS is a progressive Node.js framework that uses TypeScript by default and is heavily inspired by Angular. This article will guide you through creating a secure REST API with NestJS and JSON Web Tokens (JWT) for authentication.

What is NestJS?

NestJS is a powerful framework that allows developers to build efficient and scalable server-side applications. It leverages modern JavaScript and TypeScript features, making it a great choice for developers looking for a structured way to build applications.

Key Features of NestJS:

  • Modular Architecture: Easily manage code with modules.
  • Dependency Injection: Promote code reusability and maintainability.
  • Built-in Support for TypeScript: Leverage strong typing for better development experience.
  • Extensive Documentation: Provides comprehensive guides and examples.

Understanding JWT Authentication

JSON Web Tokens (JWT) are an open standard (RFC 7519) for securely transmitting information between parties as a JSON object. They are compact, URL-safe, and can be verified and trusted because they are digitally signed.

How JWT Works:

  1. User Login: The user authenticates with their credentials.
  2. Token Issuance: The server generates a JWT and sends it back to the user.
  3. Token Storage: The user stores the token (usually in local storage).
  4. Token Usage: For every subsequent request, the user sends the token in the Authorization header.
  5. Server Validation: The server validates the token and allows or denies access based on its validity.

Use Cases for a Secure REST API

Creating a secure REST API is essential for applications where user data is sensitive or needs protection. Use cases include: - E-commerce Platforms: Secure user accounts and transaction data. - Social Media Apps: Protect user profiles and posts. - Financial Services: Safeguard sensitive financial information.

Step-by-Step Guide to Building a Secure REST API with NestJS and JWT

Prerequisites

Before we dive in, ensure you have: - Node.js installed. - NestJS CLI installed (npm i -g @nestjs/cli). - Basic knowledge of TypeScript and RESTful APIs.

Step 1: Setting up the NestJS Project

Create a new NestJS project by running:

nest new jwt-auth-api
cd jwt-auth-api

Step 2: Install Required Packages

Install the required dependencies for JWT and password hashing:

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

Step 3: Create the Auth Module

Generate an authentication module:

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

Step 4: Implementing JWT Authentication

4.1 Create User Entity

Create a simple user entity to store user data. In src/auth/user.entity.ts:

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  username: string;

  @Column()
  password: string;
}

4.2 User Registration

In auth.service.ts, implement a method to register a new user:

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

@Injectable()
export class AuthService {
  private users: User[] = []; // This can be replaced with a database

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

4.3 JWT Generation

Add the login functionality in auth.service.ts:

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

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

  async login(username: string, password: string): Promise<string> {
    const user = this.users.find(u => u.username === username);
    if (user && await bcrypt.compare(password, user.password)) {
      const payload = { username: user.username, sub: user.id };
      return this.jwtService.sign(payload);
    }
    throw new Error('Invalid credentials');
  }
}

Step 5: Protecting Routes with Guards

Create a JWT authentication guard in auth/jwt-auth.guard.ts:

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

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

Step 6: Create AuthController

In auth.controller.ts, handle user registration and login:

import { Controller, Post, Body, UseGuards } from '@nestjs/common';
import { AuthService } from './auth.service';
import { JwtAuthGuard } from './jwt-auth.guard';

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

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

  @Post('login')
  login(@Body() body: { username: string; password: string }) {
    return this.authService.login(body.username, body.password);
  }

  @UseGuards(JwtAuthGuard)
  @Post('protected')
  protectedRoute() {
    return { message: 'You have access to this route!' };
  }
}

Step 7: Testing Your API

Now that your API is set up, you can use tools like Postman or Insomnia to test the registration and login endpoints.

  1. Register a User: Send a POST request to /auth/register.
  2. Login: Send a POST request to /auth/login to receive a JWT.
  3. Access Protected Route: Send a POST request to /auth/protected with the token in the Authorization header.

Conclusion

By following this guide, you have created a secure REST API using NestJS with JWT authentication. This setup allows for efficient user management and protects sensitive data through secure token-based authentication. Remember to always validate and sanitize user input to enhance security further.

As you continue to develop your API, consider additional features such as role-based access control, refresh tokens, and error handling to make your application more robust and secure. 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.