DEV Community

Tao Christopher Takahashi
Tao Christopher Takahashi

Posted on

Setting Up an Nginx Reverse Proxy with an Authentication System (NestJS Example)

Introduction

Nginx is a powerful web server that can also act as a reverse proxy, load balancer, and caching server. One of its common use cases is to serve as a reverse proxy in front of multiple backend services while handling authentication at the proxy level.

In this post, we’ll cover how to:

  • Set up an Nginx reverse proxy for a NestJS backend.
  • Implement an authentication system to control access to backend services.
  • Secure and optimize the configuration.

Why Use an Nginx Reverse Proxy?

A reverse proxy helps by:

  • Enhancing security: Hiding internal services from direct exposure.
  • Load balancing: Distributing traffic across multiple instances.
  • Centralized authentication: Enforcing authentication before requests reach backend services.
  • SSL termination: Handling HTTPS at the proxy level to offload encryption work.

Setting Up a NestJS Backend

First, let’s create a simple NestJS backend that will be proxied by Nginx.

1. Install NestJS CLI and Create a Project

npm i -g @nestjs/cli
nest new my-backend
cd my-backend
Enter fullscreen mode Exit fullscreen mode

2. Create an Authentication Module

nest generate module auth
nest generate controller auth
nest generate service auth
Enter fullscreen mode Exit fullscreen mode

Modify auth.service.ts to return a mock authentication response:

import { Injectable } from '@nestjs/common';
@Injectable()
export class AuthService {
  validateToken(token: string): boolean {
    return token === 'valid-token';
  }
}
Enter fullscreen mode Exit fullscreen mode

Modify auth.controller.ts to verify JWTs:

import { Controller, Get, Headers, UnauthorizedException } from '@nestjs/common';
import { AuthService } from './auth.service';

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

  @Get('validate')
  validateToken(@Headers('authorization') authHeader: string) {
    if (!authHeader || !this.authService.validateToken(authHeader.split(' ')[1])) {
      throw new UnauthorizedException();
    }
    return { status: 'valid' };
  }
}
Enter fullscreen mode Exit fullscreen mode

Run the backend:

npm run start
Enter fullscreen mode Exit fullscreen mode

By default, it will run on http://localhost:3000.

Configuring Nginx as a Reverse Proxy for NestJS

1. Install Nginx

sudo apt update && sudo apt install nginx -y
Enter fullscreen mode Exit fullscreen mode

2. Configure the Reverse Proxy

Edit the Nginx configuration file:

sudo nano /etc/nginx/sites-available/reverse-proxy.conf
Enter fullscreen mode Exit fullscreen mode

Add the following configuration:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:3000;  # Forward requests to NestJS
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
Enter fullscreen mode Exit fullscreen mode

Save and create a symbolic link:

sudo ln -s /etc/nginx/sites-available/reverse-proxy.conf /etc/nginx/sites-enabled/
sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

This configuration forwards requests to the NestJS backend.

Adding an Authentication Layer

To restrict access, we can introduce an authentication mechanism.

1. JWT Authentication with Nginx and NestJS

We’ll modify our Nginx configuration to validate JWTs by forwarding authentication requests to the NestJS auth service.

Edit the Nginx configuration:

location / {
    auth_request /auth/validate;
    error_page 401 = @error401;
    proxy_pass http://localhost:3000;
}

location /auth/validate {
    proxy_pass http://localhost:3000/auth/validate;
    internal;
}

location @error401 {
    return 401 "Unauthorized";
}
Enter fullscreen mode Exit fullscreen mode

Here, before forwarding any request to the backend, Nginx calls /auth/validate. If it returns 401, the request is blocked.

Securing Nginx

  • Enable HTTPS with Let’s Encrypt:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
Enter fullscreen mode Exit fullscreen mode
  • Limit Request Rates to prevent brute-force attacks:
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
location / {
    limit_req zone=mylimit burst=20 nodelay;
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Using Nginx as a reverse proxy with authentication for a NestJS backend provides a secure and scalable way to manage access to backend services. By leveraging JWT authentication, we ensure requests are validated before reaching our backend services.

Top comments (0)