Skip to content

Feature: Secure Authentication via Middleware Proxy #1

@Sunja-An

Description

@Sunja-An

Issue Update: Secure Authentication via Next.js Middleware Proxy

🚀 Feature Implementation

We have successfully implemented a Next.js Middleware Proxy to handle authentication securely using HttpOnly cookies.

🛑 The Problem

Our backend API requires an Authorization: Bearer <token> header for authenticated requests. However, to enhance security and prevent Cross-Site Scripting (XSS) attacks, we store the Access Token in an HttpOnly Cookie.

Since client-side JavaScript (api-client.ts) cannot read HttpOnly cookies, it cannot manually attach the Authorization header to requests. This resulted in 401 Unauthorized errors when calling API endpoints directly from the browser.

✅ The Solution

We implemented a Server-Side Proxy using Next.js Middleware (src/middleware.ts).

  1. Interception: The Middleware listens for all requests matching /api/proxy/*.
  2. Cookie Access: Since the Middleware runs on the Next.js server, it has access to the incoming request's cookies (including HttpOnly ones).
  3. Header Injection: The Middleware extracts the access_token from the cookie and consistently injects it into the Authorization header.
  4. URL Rewrite: The request is then rewritten (proxied) to the actual Backend API URL (e.g., http://localhost:8080/api/...).

📦 Key Changes

1. Middleware (src/middleware.ts)

export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/api/proxy')) {
    // 1. Read the HttpOnly cookie
    const accessToken = request.cookies.get('access_token')?.value;
    
    // 2. Rewrite URL to Backend
    const path = request.nextUrl.pathname.replace('/api/proxy', '');
    const targetUrl = `${process.env.NEXT_PUBLIC_API_URL}${path}`;

    // 3. Inject Authorization Header
    const requestHeaders = new Headers(request.headers);
    if (accessToken) {
      requestHeaders.set('Authorization', `Bearer ${accessToken}`);
    }

    return NextResponse.rewrite(new URL(targetUrl), {
      request: { headers: requestHeaders },
    });
  }
}

2. API Client (src/lib/api-client.ts)

Updated the Base URL to route requests through the proxy:

// Before: Direct to Backend
// const BASE_URL = process.env.NEXT_PUBLIC_API_URL; 

// After: Through Local Middleware
const BASE_URL = '/api/proxy'; 

🔒 Benefits

  • Security: Tokens are never exposed to client-side code, mitigating XSS risks.
  • Transparency: Standard API calls work without manual token management in components.
  • Reliability: The server handles the token attachment, ensuring headers are always present for valid sessions.

Created by Antigravity Agent

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions