Home » [SOLVED] Cross-Origin Request Blocked in Next.js Route Handlers & API Routes
Web & Code

[SOLVED] Cross-Origin Request Blocked in Next.js Route Handlers & API Routes

When accessing Next.js API endpoints (via modern App Router app/api/.../route.ts or legacy pages/api/...) from third-party client apps (React Native, Flutter, external web subdomains), modern browsers abort requests with: Access to fetch at ... from origin ... has been blocked by CORS policy: Response to preflight request doesn't pass access control check.

Quick Diagnostics

Cause
Missing Access-Control-Allow-Origin headers on Next.js App Router Response objects
Solution
Define global headers in next.config.js or implement CORS response middleware
Cause
Browser preflight OPTIONS requests receiving 405 Method Not Allowed inside route.js
Solution
Export an explicit OPTIONS handler function in app/api/.../route.js

Step-by-Step Solution

  1. 1

    Step 1: Implement Explicit OPTIONS Preflight Route Handler

    Browsers issue a preflight OPTIONS probe prior to sending requests with custom headers or non-simple HTTP verbs. In app/api/your-route/route.js:

    JAVASCRIPT
    const corsHeaders = {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    };
    
    export async function OPTIONS() {
      return new Response(null, {
        status: 204,
        headers: corsHeaders,
      });
    }
    
    export async function GET(request) {
      return Response.json({ success: true }, { headers: corsHeaders });
    }
    
  2. 2

    Step 2: Enforce Global API CORS Headers in next.config.js

    For monolithic APIs with numerous routes, register CORS rules globally at the server engine level:

    JAVASCRIPT
    /** @type {import('next').NextConfig} */
    const nextConfig = {
      async headers() {
        return [
          {
            source: "/api/:path*",
            headers: [
              { key: "Access-Control-Allow-Credentials", value: "true" },
              { key: "Access-Control-Allow-Origin", value: "*" },
              { key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT,OPTIONS" },
              { key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, Authorization" },
            ]
          }
        ];
      }
    };
    
    module.exports = nextConfig;
    
  3. 3

    Step 3: Handle Authenticated Credential Transmission

    When requests carry HTTP-only session cookies or authorization tokens via credentials: 'include', wildcard * origins trigger security rejections. Bind your exact origin domain explicitly:

    JAVASCRIPT
    'Access-Control-Allow-Origin': 'https://app.clientdomain.com',
    'Access-Control-Allow-Credentials': 'true'
    

Frequently Asked Questions

Why did this endpoint succeed in local development but fail in production?

Local environments often share origin ports or run on localhost bypasses. Production brings distinct FQDNs, which immediately trigger browser preflight security policies.

Can Next.js Middleware handle CORS for all routes at once?

Yes. Create middleware.js in your project root matching /api/:path* to append headers to every outgoing NextResponse.

Prevention Advice

Recommended security practices:

  • Never leave wildcard origins * active in production if returning private user records.
  • Consider implementing Next.js Edge Middleware for granular dynamic origin verification.
Author • Web Designer & App Creator

Rodolfo Castro

Web designer, app developer, and founder of SoporteCero. Specializing in UI/UX architecture, digital products, and modern web environments (Pixel Digital Dz). Every tutorial and guide on SoporteCero is thoroughly tested and verified in our technical lab to ensure reliable, up-to-date solutions.