Skip to content

JayShende/Proxy-Backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Proxy Backend for TurboRepo Architecture

A secure proxy backend that acts as a bridge between your Next.js frontend and Express backend in a TurboRepo monorepo setup. This proxy provides an additional layer of security by hiding your actual backend URL and implementing JWT-based authentication for protected routes.

πŸ—οΈ Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Next.js FE    │───▢│   Proxy Backend  │───▢│  Express BE     β”‚
β”‚   (Frontend)    β”‚    β”‚   (This App)     β”‚    β”‚   (Hidden)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ” Security Features

  • URL Hiding: Your Express backend URL is completely hidden from the frontend
  • JWT Authentication: Internal JWT tokens for secure communication between proxy and Express backend
  • NextAuth Integration: Seamless integration with NextAuth.js for user authentication
  • Public Routes: Support for public endpoints that don't require authentication
  • Session Validation: Automatic session validation for protected routes

πŸ“ File Structure

app/
└── api/
    └── proxy/
        └── [...path]/
            └── route.ts  # Main proxy implementation

πŸš€ Getting Started

Prerequisites

  1. NextAuth.js Setup: Install and configure NextAuth.js using Boltgate CLI
  2. Express Backend: Your Express backend should be running and accessible
  3. Environment Variables: Configure the required environment variables

Installation

  1. Install dependencies:
npm install
# or
pnpm install
  1. Set up NextAuth.js using Boltgate:
npx boltgate
  1. Configure environment variables in .env.local:
# Express Backend URL (hidden from frontend)
EXPRESS_URL=http://localhost:8000

# JWT Secret for internal communication
INTERNAL_JWT_SECRET=your-super-secret-jwt-key

# NextAuth.js configuration (generated by Boltgate)
NEXTAUTH_SECRET=your-nextauth-secret
NEXTAUTH_URL=http://localhost:3000

πŸ”§ Configuration

Environment Variables

Variable Description Required
EXPRESS_URL Your Express backend base URL βœ…
INTERNAL_JWT_SECRET Secret key for internal JWT signing βœ…
NEXTAUTH_SECRET NextAuth.js secret (from Boltgate) βœ…
NEXTAUTH_URL Your Next.js app URL βœ…

Public Routes Configuration

Edit the PUBLIC_ROUTES array in app/api/proxy/[...path]/route.ts:

const PUBLIC_ROUTES: string[] = [
  "/api/proxy/v1/form/getForm", // Example public route
  "/api/proxy/v1/public/data", // Another public route
  "/api/proxy/v1/health", // Health check endpoint
];

Note: Public routes don't require authentication and won't include JWT tokens in the request to your Express backend.

πŸ“‘ API Usage

Making Requests

All requests to your Express backend should be made through the proxy:

// ❌ Don't do this (exposes your backend URL)
fetch("http://localhost:8000/api/users");

// βœ… Do this instead
fetch("/api/proxy/v1/users");

Request Examples

1. Public Route (No Authentication Required)

// Frontend request
const response = await fetch("/api/proxy/v1/public/data", {
  method: "GET",
});

2. Protected Route (Authentication Required)

// Frontend request (user must be authenticated via NextAuth)
const response = await fetch("/api/proxy/v1/users/profile", {
  method: "GET",
  headers: {
    "Content-Type": "application/json",
  },
});

3. POST Request with Data

const response = await fetch("/api/proxy/v1/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "John Doe",
    email: "john@example.com",
  }),
});

πŸ”’ Express Backend Integration

Required Middleware

Your Express backend needs to verify the JWT tokens sent by the proxy:

// middleware/auth.ts
import jwt from "jsonwebtoken";
import { Request, Response, NextFunction } from "express";

interface AuthenticatedRequest extends Request {
  userId?: string;
}

const verifyInternalJWT = (
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
) => {
  const authHeader = req.headers.authorization;

  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return res.status(401).json({ message: "No token provided" });
  }

  const token = authHeader.split(" ")[1];

  try {
    const decoded = jwt.verify(token, process.env.INTERNAL_JWT_SECRET!) as {
      userId: string;
    };
    req.userId = decoded.userId;
    next();
  } catch (error) {
    return res.status(401).json({ message: "Invalid token" });
  }
};

export { verifyInternalJWT };

Route Protection

// routes/protected.ts
import express, { Request, Response } from "express";
import { verifyInternalJWT } from "../middleware/auth";
const router = express.Router();

// Protected route (requires JWT)
router.get(
  "/users/profile",
  verifyInternalJWT,
  (req: Request, res: Response) => {
    res.json({ userId: (req as any).userId, message: "Protected data" });
  }
);

// Public route (no middleware needed)
router.get("/public/data", (req: Request, res: Response) => {
  res.json({ message: "Public data" });
});

export default router;

πŸ› οΈ Development

Running the Development Server

npm run dev
# or
pnpm dev

The proxy will be available at http://localhost:3000/api/proxy/

Testing the Proxy

  1. Test Public Route:
curl http://localhost:3000/api/proxy/v1/public/data
  1. Test Protected Route (requires authentication):
# This will return 401 if not authenticated
curl http://localhost:3000/api/proxy/v1/users/profile

πŸ” How It Works

Request Flow

  1. Frontend Request: Client makes request to /api/proxy/your-endpoint
  2. Route Parsing: Proxy extracts the path after /api/proxy/
  3. Authentication Check:
    • If route is public β†’ Skip authentication
    • If route is protected β†’ Validate NextAuth session
  4. JWT Signing: For authenticated requests, sign internal JWT with user ID
  5. Backend Request: Forward request to Express backend with JWT header
  6. Response Forwarding: Return Express backend response to frontend

Security Benefits

  • URL Hiding: Express backend URL is never exposed to the frontend
  • JWT Protection: Internal JWT tokens expire in 5 minutes for security
  • Session Validation: Only authenticated users can access protected routes
  • Error Handling: Graceful error handling and response forwarding

πŸ“ Customization

Adding New Public Routes

const PUBLIC_ROUTES: string[] = [
  "/api/proxy/v1/form/getForm",
  "/api/proxy/v1/public/data",
  "/api/proxy/v1/health", // Add new public routes here
  "/api/proxy/v1/analytics/track", // Example: analytics tracking
];

Modifying JWT Expiration

// In the signInternalJwt function
return jwt.sign({ userId }, process.env.INTERNAL_JWT_SECRET, {
  expiresIn: "10m", // Change from 5m to 10m
});

Adding Custom Headers

// In the proxyRequest function
const headers: Record<string, string> = {
  "Content-Type": req.headers.get("content-type") || "application/json",
  "X-Custom-Header": "your-value", // Add custom headers
};

🚨 Troubleshooting

Common Issues

  1. 401 Session Error: Make sure NextAuth.js is properly configured
  2. Backend Connection Failed: Verify EXPRESS_URL is correct and backend is running
  3. JWT Verification Failed: Ensure INTERNAL_JWT_SECRET matches between proxy and Express backend
  4. CORS Issues: Configure CORS in your Express backend to allow requests from your Next.js domain

Debug Mode

Enable detailed logging by adding console.log statements in the proxy function:

console.log("Request URL:", backendUrl);
console.log("Headers:", headers);
console.log("User ID:", userId);

πŸ“š Additional Resources

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Test thoroughly
  5. Submit a pull request

πŸ“„ License

This project is licensed under the MIT License.


Made with ❀️ by Jay Shende

About

A secure proxy backend that acts as a bridge between your Next.js frontend and Express backend in a TurboRepo monorepo setup. This proxy provides an additional layer of security by hiding your actual backend URL and implementing JWT-based authentication for protected routes.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors