Skip to content

nmrisrl11/nestjs-authentication-api

Repository files navigation

AuthForge

Overview

AuthForge is a production-inspired authentication API built with NestJS, showcasing modern backend architecture, secure JWT authentication, Drizzle ORM, PostgreSQL, Redis, BullMQ, and interchangeable infrastructure providers.

Originally started from a YouTube authentication course, the project has since evolved into a significantly enhanced codebase featuring modular architecture, asynchronous email processing, infrastructure abstraction, Docker-based local development, and numerous quality-of-life improvements that better reflect real-world backend development practices.

🔗 Repository: https://github.com/nmrisrl11/nestjs-authentication-api


🚀 Tech Stack

  • Framework: NestJS (Express under the hood)
  • Database: PostgreSQL (via Neon or Local Docker)
  • ORM: Drizzle ORM
  • Caching / Queues: Redis (via Upstash or Local Docker) & BullMQ
  • Email Providers: Nodemailer / Resend
  • Validation & Type Safety: Zod & T3 Env
  • API Documentation: Swagger UI
  • Code Quality: Prettier, ESLint, Greptile

✨ Features & Improvements

Core Features (From Original Course)

  • Custom Authentication: Full JWT-based auth flow (Access & Refresh tokens).
  • Token Management: Hashing/saving refresh tokens to the DB and setting them in HTTP-only client cookies.
  • Account Verification: Email verification route and user creation upon registration.
  • Password Recovery: Forgot password flow with expiring reset tokens.
  • Role-Based Access Control (RBAC): Dedicated Admin module for listing/deleting users.
  • Rate Limiting: Integrated NestJS Throttler.
  • Task Module: Basic CRUD operations for tasks.

🛠️ Advanced Enhancements (Post-Tutorial)

  • Modular Architecture: Strictly decoupled codebase with a dedicated modules/ layer.
  • Email Service Abstraction: Separated email logic into its own module. Created an abstract provider token to seamlessly swap between Nodemailer and Resend using NestJS's useClass.
  • Background Jobs (BullMQ + Redis): Offloaded email sending from the main execution thread to a background queue. Includes Bull Board integration for a visual queue dashboard (protected by middleware).
  • Type-Safe Environments: Opted into @t3-oss/env-core to guarantee environment variables are present and correctly typed at build time.
  • Drizzle ORM Injectable: Converted Drizzle database initialization into an injectable NestJS Module.
  • Custom CLI Tooling: Built a custom script (npm run create:resource) to quickly scaffold a Module, Service, and Controller inside the modules layer.
  • Security & Data Privacy:
    • Admin users are prevented from deleting their own accounts.
    • Sensitive user data is filtered out before being returned in admin endpoints.
    • Proper UUID validation across all routes expecting UUIDs.
  • Resilience: Added a fallback method for resending verification emails if the initial registration email fails.
  • Code Quality: Enforced a project-wide Prettier configuration (tabs over spaces, double quotes, semicolons), unified DTOs, and integrated Greptile for PR vulnerability/quality checks.

🔀 Interchangeable Infrastructure Options

This project is built to be environment-agnostic, allowing you to easily swap out infrastructure providers just by changing variables in your .env file.

Database: Neon vs. Docker

  • Neon: Set DATABASE_URL to your Neon serverless Postgres connection string.
  • Docker: Set DATABASE_URL to point to localhost:5432 and use npm run services:up to spin up the local Postgres container.

Queues: Upstash vs. Docker

  • Upstash: Provide your Upstash Redis connection string to REDIS_URL.
  • Docker: Point REDIS_URL to your local Docker Redis instance (redis://localhost:6379).

Email: Nodemailer vs. Resend

Change the EMAIL_PROVIDER env variable to either nodemailer or resend. The application will automatically inject the correct provider class at runtime. Handlebars templates are fully supported on both ends.

⚙️ Environment Variables

Create a .env file in the root directory. You can use the .env.example as a template:

NODE_ENV= # "development", "test", or "production"

# --- DATABASE ---
DATABASE_URL= # Neon URL or Docker local Postgres URL
POSTGRES_USER= # Local Docker DB User
POSTGRES_PASSWORD= # Local Docker DB Password
POSTGRES_DB= # Local Docker DB Name

# --- AUTHENTICATION ---
# Generate via: node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
JWT_ACCESS_SECRET=
JWT_ACCESS_EXPIRES_IN=
JWT_REFRESH_SECRET=
JWT_REFRESH_EXPIRES_IN=

# --- APP CONFIG ---
APP_URL=http://localhost:3000
PORT=3000

# --- EMAIL PROVIDERS ---
EMAIL_PROVIDER= # "nodemailer" or "resend"
RESEND_API_KEY=
FROM_EMAIL= # Default to onboarding@resend.dev if using Resend

# Nodemailer SMTP Config
SMTP_HOST= # e.g., smtp.gmail.com
SMTP_PORT= # 587 or 465
SMTP_SECURE= # true for 465, false for 587
SMTP_USER= # Your email address
SMTP_PASS= # App Password

# --- QUEUES (REDIS) ---
REDIS_URL= # Upstash URL or Local Docker Redis URL
BULL_BOARD_USER= # Optional: Dashboard username
BULL_BOARD_PASSWORD= # Optional: Dashboard password

📦 Getting Started

  1. Installation
npm install
  1. Database Migrations Generate and push the Drizzle schema to your database:
npm run db:generate
npm run db:push
  1. Running the App Option A: Fully Local (With Docker) Runs the NestJS server alongside PostgreSQL and Redis containers.
npm run dev:full

Note: If you stop the app using Ctrl+C, the Docker containers will remain running in the background. To stop them, run npm run services:down.

Option B: Standard Development (Cloud DB/Redis) Runs just the NestJS server. Ensure your DATABASE_URL and REDIS_URL are pointing to your cloud providers (Neon/Upstash). Note: If no Redis is connected, background queues will be mocked/fail.

npm run start:dev
  1. Code Generation Tool To quickly generate a new resource module inside the src/modules folder:
npm run create:resource

🌿 Branches & Integrations

Throughout the development process, specific features were isolated into their own branches for easier tracking. You can explore the repository branches to see the integration.

(Check the GitHub branches tab for the full list)

🧠 What I've Learned

Building AuthForge went far beyond a standard tutorial. Key takeaways from scaling this architecture include:

  1. Dependency Injection & Abstraction: Learning to use NestJS's useClass to create abstract contracts (like the Email Provider) made the codebase incredibly flexible, allowing me to swap between Resend and Nodemailer without touching the core authentication logic.

  2. Background Processing: Integrating BullMQ and Redis taught me the importance of offloading heavy tasks (like sending emails) to prevent blocking the main event loop, significantly improving API response times.

  3. Type-Safe Environments: Catching misconfigured .env variables at build time with T3 Env (Zod) prevented hard-to-debug runtime errors related to missing database URLs or JWT secrets.

  4. Modular Monolith Design: Moving away from a flat structure and grouping features into a cohesive modules/ layer improved maintainability and enforced the DRY principle across services.

  5. Infrastructure Automation: Integrating Docker Compose for local development made the transition between local and cloud providers (Neon/Upstash) seamless, deeply improving my local developer experience (DX).

Acknowledgements

Initial inspiration and core authentication flow derived from the NestJS Authentication Full Course by code with lari.

About

A modern NestJS Authentication API demonstrating Drizzle ORM, PostgreSQL (Neon or Docker), email services (Nodemailer/Resend), BullMQ, Redis (Upstash/Docker), and Swagger with interchangeable infrastructure options.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors