Skip to content

Rohit-Pakhre09/sentrix

Repository files navigation

Next.js Authentication System

Next.js TypeScript Tailwind CSS Node.js MongoDB pnpm Nodemailer Argon2 License: MIT

A robust and secure authentication backend built with Next.js, TypeScript, and MongoDB. This project provides a complete, production-ready authentication solution with features like JWT-based authentication, refresh tokens, secure password handling, and standardized API responses.

Overview

This project is a full-featured authentication backend powered by Next.js API routes. It demonstrates best practices for building secure and scalable authentication systems, including the use of a hybrid token strategy (access and refresh tokens), secure password hashing with Argon2, and safe cookie handling. It also features a standardized API structure for consistent error handling and responses.

Features

  • User Registration: Create new user accounts with passwords securely hashed using Argon2, a modern, memory-hard hashing algorithm.
  • Email Verification: After registration, users receive a verification email with a secure link. Upon clicking, they are automatically redirected to the login page.
  • User Login: Authenticate users and issue JSON Web Tokens (JWT).
  • Hybrid Authentication: Implements a robust token-based session management system.
    • Short-lived Access Tokens: For authorizing API requests (15-minute expiry).
    • Long-lived Refresh Tokens: For obtaining new access tokens without re-login (1-day expiry).
  • Secure Cookie Storage: Both access and refresh tokens are stored in HttpOnly cookies to prevent XSS attacks.
  • Password Reset Flow: A complete and secure "forgot password" feature that sends a time-limited (1-hour) reset link to the user's email.
  • Professional Email Templates: Modern and responsive HTML email templates for a better user experience.
  • Protected Routes: Example of a protected GET /api/auth/me route that verifies the access token.
  • Standardized API: Consistent API error and response handling using a reusable pattern.

Security Considerations

This project was built with security as a top priority.

  • Password Hashing: We use Argon2, the winner of the Password Hashing Competition, which is highly resistant to both GPU cracking attacks and side-channel attacks.
  • JWT Security:
    • Access tokens are short-lived to minimize the impact of a potential leak.
    • Refresh tokens are stored in the database and can be invalidated on logout, providing a mechanism to revoke access.
  • Cookie Security: HttpOnly cookies are used to store tokens, making them inaccessible to client-side JavaScript. This is a critical defense against Cross-Site Scripting (XSS) attacks. Secure cookies are used in production to ensure they are only sent over HTTPS.
  • User Enumeration Prevention: The /api/auth/forgot-password endpoint always returns a success response to prevent attackers from discovering which emails are registered in the system.

Codebase Standardization

To ensure consistency and maintainability, the API routes follow a standard pattern using custom utilities:

  • asyncHandler: A higher-order function that wraps all API route handlers. It provides a centralized try...catch block to handle any uncaught errors, preventing the server from crashing and ensuring a consistent error response is always sent.
  • ApiError: A custom Error class used for operational errors (e.g., "User not found", "Invalid password"). It includes an HTTP status code, which allows the asyncHandler to send the correct response.
  • ApiResponse: A custom class that standardizes the structure of all successful JSON responses, ensuring consistency for the client.

Project Structure

The project follows a feature-based structure within the src directory to promote modularity and ease of maintenance.

/src
├── app/
│   ├── api/auth/            # API routes for authentication endpoints (register, login, etc.)
│   ├── favicon.ico          # Favicon for the application
│   ├── globals.css          # Global CSS styles
│   ├── layout.tsx           # Root layout component
│   ├── page.tsx             # Home page component
│   ├── forgot-password/     # Page for password reset request
│   ├── home/                # Protected home page after login
│   ├── login/               # Login page
│   ├── register/            # Registration page
│   └── reset-password/      # Page for resetting password
├── components/
│   └── AuthForm.tsx         # Reusable authentication form component
├── lib/
│   └── db.ts                # MongoDB connection and database utilities
├── models/
│   └── User.ts              # Mongoose schema for User model
└── utils/
    ├── ApiError.ts          # Custom error class for API responses
    ├── ApiResponse.ts       # Custom response class for standardized API outputs
    ├── asyncHandler.ts      # Higher-order function for async error handling
    ├── auth.ts              # Utilities for JWT token generation and verification
    └── emailTemplates.ts    # HTML templates for email notifications

Getting Started

Prerequisites

  • Node.js (v18 or later)
  • pnpm (recommended)
  • MongoDB instance (local or cloud-hosted)

Installation & Setup

  1. Clone the repository:

    git clone <repository-url>
    cd <repository-name>
  2. Install dependencies:

    pnpm install
  3. Set up environment variables: Create a file named .env.local in the root of the project and add the variables from the template below. Never commit this file to version control.

    # MongoDB Connection String
    # Connects to your local or cloud-hosted MongoDB database.
    MONGODB_URI=your_mongodb_connection_string
    
    # Base URL of the application
    # Used for creating absolute links in emails.
    BASE_URL=http://localhost:3000
    
    # JWT secrets
    # Use a strong, random string (32+ characters) for each.
    # You can generate one with: openssl rand -hex 32
    JWT_ACCESS_SECRET_KEY=your_super_secret_access_key_32_chars_or_more
    JWT_REFRESH_SECRET_KEY=your_super_secret_refresh_key_32_chars_or_more
    
    # Gmail credentials for sending emails.
    # For security, it is highly recommended to use a Google App Password
    # instead of your regular password.
    EMAIL_USERNAME=your_gmail_username@gmail.com
    EMAIL_PASSWORD=your_gmail_app_password
  4. Run the development server:

    pnpm dev

The application will be available at http://localhost:3000.

API Endpoints

Below is a detailed list of the available API endpoints, including request examples using curl and expected JSON responses.

POST /api/auth/register

Registers a new user account.

Request Example:

curl -X POST http://localhost:3000/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securepassword123"
  }'

Success Response (201):

{
  "success": true,
  "message": "User registered successfully",
  "data": {
    "user": {
      "id": "user_id",
      "email": "user@example.com"
    }
  }
}

POST /api/auth/login

Authenticates a user and issues access and refresh tokens.

Request Example:

curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "securepassword123"
  }'

Success Response (200):

{
  "success": true,
  "message": "Login successful",
  "data": {
    "user": {
      "id": "user_id",
      "email": "user@example.com"
    }
  }
}

Note: Tokens are set in HttpOnly cookies.

POST /api/auth/logout

Logs out the user by invalidating the refresh token.

Request Example:

curl -X POST http://localhost:3000/api/auth/logout \
  -H "Cookie: refreshToken=your_refresh_token"

Success Response (200):

{
  "success": true,
  "message": "Logout successful"
}

GET /api/auth/me

Retrieves the authenticated user's information. Requires a valid access token.

Request Example:

curl -X GET http://localhost:3000/api/auth/me \
  -H "Cookie: accessToken=your_access_token"

Success Response (200):

{
  "success": true,
  "data": {
    "user": {
      "id": "user_id",
      "email": "user@example.com"
    }
  }
}

POST /api/auth/refresh

Refreshes the access token using a valid refresh token.

Request Example:

curl -X POST http://localhost:3000/api/auth/refresh \
  -H "Cookie: refreshToken=your_refresh_token"

Success Response (200):

{
  "success": true,
  "message": "Token refreshed successfully"
}

Note: New access token is set in cookie.

POST /api/auth/forgot-password

Sends a password reset email to the user.

Request Example:

curl -X POST http://localhost:3000/api/auth/forgot-password \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com"
  }'

Success Response (200):

{
  "success": true,
  "message": "If an account with that email exists, a reset link has been sent."
}

POST /api/auth/reset-password

Resets the user's password using a valid reset token.

Request Example:

curl -X POST http://localhost:3000/api/auth/reset-password \
  -H "Content-Type: application/json" \
  -d '{
    "token": "reset_token_from_email",
    "newPassword": "newsecurepassword123"
  }'

Success Response (200):

{
  "success": true,
  "message": "Password reset successfully"
}

Testing

To test the API endpoints, you can use tools like Postman or curl commands. Ensure the development server is running (pnpm dev).

  1. Using Postman:

    • Import the API endpoints as a collection.
    • Set up environment variables for base URL (e.g., http://localhost:3000).
    • For endpoints requiring authentication, include cookies in the request (accessToken or refreshToken).
  2. Using curl:

    • Refer to the examples in the API Endpoints section above.
    • Note that cookies are handled automatically in browsers, but with curl, you may need to manage them manually or use tools like httpie.
  3. Automated Testing:

    • Consider using Jest or similar for unit and integration tests.
    • Example: Test user registration by sending a POST request and verifying the response.

Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository.
  2. Create a new branch for your feature or bug fix.
  3. Make your changes and ensure tests pass.
  4. Submit a pull request with a clear description of the changes.

Please adhere to the existing code style and include tests for new features.

Technologies Used

License

This project is licensed under the MIT License.

About

A secure authentication system that verifies user identity with modern best practices.

Topics

Resources

License

Stars

Watchers

Forks

Contributors