Claude Code के साथ CORS Configuration Guide: सुरक्षित Cross-Origin API
Claude Code से CORS सुरक्षित configure करें: preflight, credentials, origin allowlist, test commands और review prompts.
Claude Code से CORS सही तरीके से configure करें
Frontend अगर localhost:3000 पर है और API localhost:8787 पर, तो browser तुरंत CORS error दिखा सकता है। जल्दी में लोग अक्सर Access-Control-Allow-Origin: * जोड़ देते हैं, लेकिन API में cookie, Authorization header या admin panel हो तो यह unsafe हो सकता है।
CORS, यानी Cross-Origin Resource Sharing, वह browser mechanism है जिससे server बताता है कि कौन से दूसरे origins उसकी response पढ़ सकते हैं। Origin scheme, host और port का combination है। https://app.example.com, https://api.example.com, http://localhost:3000 और http://localhost:5173 अलग-अलग origins हैं।
यह guide CORS configuration को ऐसे हिस्सों में तोड़ती है जिन्हें Claude Code से generate कराने के बाद आप review कर सकें। इसमें Express, Fastify, Cloudflare Workers और Next.js Route Handler के copy-paste examples, preflight, credentials, origin allowlist, test commands और Claude Code review prompts शामिल हैं।
सबसे जरूरी बात: CORS authentication नहीं है। यह सिर्फ control करता है कि browser JavaScript cross-origin response पढ़ सके या नहीं। यह curl, server-to-server calls या unauthorized users को नहीं रोकता। API authentication, authorization, CSRF, rate limiting और security headers अलग से design करें।
sequenceDiagram
participant Browser as Browser
participant API as API server
Browser->>API: OPTIONS /api/messages<br/>Origin + Access-Control-Request-*
API-->>Browser: 204 + Access-Control-Allow-*
Browser->>API: POST /api/messages<br/>Cookie or Authorization
API-->>Browser: 200 + Access-Control-Allow-Origin
Code लिखने से पहले decisions
Claude Code से CORS middleware लिखवाने से पहले ये चार बातें तय करें। अगर prompt vague होगा, तो वह demo-friendly लेकिन production के लिए dangerous full-open config दे सकता है।
| Decision | Example | ध्यान दें |
|---|---|---|
| Allowed origins | https://app.example.com, https://admin.example.com | Path या trailing slash नहीं |
| Credentials | Cookie, Authorization header | Cookie flow में SameSite=None; Secure भी check करें |
| Methods | GET,POST,PUT,PATCH,DELETE,OPTIONS | सिर्फ इस्तेमाल होने वाले methods allow करें |
| Headers | Content-Type,Authorization,X-Request-ID | Preflight request से match होना चाहिए |
Preflight browser की permission check request है। JSON POST, Authorization, PUT, DELETE या custom headers से पहले browser अक्सर OPTIONS भेजता है। अगर response में matching Access-Control-Allow-Methods और Access-Control-Allow-Headers नहीं हैं, तो actual request भेजी ही नहीं जाती।
Express configuration
यह example Node.js 20 या उससे नए version के लिए है। Express का official cors middleware origin में function ले सकता है, इसलिए हर request को allowlist से check किया जा सकता है। API credentials support करती है, इसलिए केवल allowed origins reflect होंगे और credentials: true लगाया जाएगा।
npm init -y
npm install express cors
node server.mjs
// server.mjs
import express from "express";
import cors from "cors";
const app = express();
const allowedOrigins = new Set([
"https://app.example.com",
"https://admin.example.com",
"http://localhost:3000",
"http://localhost:5173",
]);
function isAllowedOrigin(origin) {
if (!origin) return true;
if (allowedOrigins.has(origin)) return true;
return process.env.NODE_ENV !== "production" && /^http:\/\/localhost:\d+$/.test(origin);
}
const corsOptions = {
origin(origin, callback) {
callback(null, isAllowedOrigin(origin));
},
credentials: true,
methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
allowedHeaders: ["Content-Type", "Authorization", "X-Request-ID"],
exposedHeaders: ["X-Request-ID"],
maxAge: 86400,
optionsSuccessStatus: 204,
};
app.use((req, res, next) => {
const origin = req.headers.origin;
if (origin && !isAllowedOrigin(origin)) {
return res.status(403).json({ error: "Origin not allowed" });
}
next();
});
app.use(cors(corsOptions));
app.use(express.json());
app.get("/api/health", (_req, res) => {
res.setHeader("X-Request-ID", crypto.randomUUID());
res.json({ ok: true });
});
app.post("/api/messages", (req, res) => {
res.setHeader("X-Request-ID", crypto.randomUUID());
res.json({ ok: true, received: req.body });
});
app.listen(8787, () => {
console.log("API listening on http://localhost:8787");
});
Production में NODE_ENV=production set करें और allowedOrigins में सिर्फ real domains रखें। जिन requests में Origin header नहीं है वे browser CORS requests नहीं होतीं, इसलिए sample उन्हें allow करता है; API key, JWT और user permissions फिर भी auth middleware में check होने चाहिए।
Fastify configuration
Fastify में @fastify/cors use करें। Official README में origin के लिए boolean, string, array, RegExp और function supported हैं, लेकिन Set-based exact match audit करना आसान है। Broad regex तभी use करें जब सच में जरूरत हो।
npm init -y
npm install fastify @fastify/cors
node server.mjs
// server.mjs
import Fastify from "fastify";
import cors from "@fastify/cors";
const app = Fastify({ logger: true });
const allowedOrigins = new Set([
"https://app.example.com",
"https://admin.example.com",
"http://localhost:3000",
"http://localhost:5173",
]);
function isAllowedOrigin(origin) {
if (!origin) return true;
if (allowedOrigins.has(origin)) return true;
return process.env.NODE_ENV !== "production" && /^http:\/\/localhost:\d+$/.test(origin);
}
app.addHook("onRequest", async (request, reply) => {
const origin = request.headers.origin;
if (origin && !isAllowedOrigin(origin)) {
return reply.code(403).send({ error: "Origin not allowed" });
}
});
await app.register(cors, {
origin(origin, callback) {
callback(null, isAllowedOrigin(origin));
},
credentials: true,
methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
allowedHeaders: ["Content-Type", "Authorization", "X-Request-ID"],
exposedHeaders: ["X-Request-ID"],
maxAge: 86400,
strictPreflight: true,
});
app.get("/api/health", async () => ({ ok: true }));
app.post("/api/messages", async (request) => {
return { ok: true, received: request.body };
});
await app.listen({ port: 8787, host: "0.0.0.0" });
Fastify में plugin और hook order important है। अगर auth hook CORS plugin से पहले OPTIONS reject कर देता है, तो browser actual request नहीं भेजेगा। Claude Code से review कराते समय registration order भी check करवाएँ।
Cloudflare Workers configuration
Cloudflare Workers standard Fetch API use करता है। OPTIONS को explicitly handle करें, success और error दोनों responses पर CORS headers लगाएँ, और origin के हिसाब से response बदलता है तो Vary: Origin जोड़ें।
// src/index.ts
const allowedOrigins = new Set([
"https://app.example.com",
"https://admin.example.com",
"http://localhost:3000",
]);
function getCorsHeaders(request: Request): HeadersInit | null {
const origin = request.headers.get("Origin");
if (!origin) return {};
if (!allowedOrigins.has(origin)) return null;
return {
"Access-Control-Allow-Origin": origin,
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
"Access-Control-Allow-Headers": "Content-Type,Authorization,X-Request-ID",
"Access-Control-Max-Age": "86400",
"Vary": "Origin",
};
}
export default {
async fetch(request: Request): Promise<Response> {
const corsHeaders = getCorsHeaders(request);
if (corsHeaders === null) {
return Response.json({ error: "Origin not allowed" }, { status: 403 });
}
if (request.method === "OPTIONS") {
return new Response(null, { status: 204, headers: corsHeaders });
}
const url = new URL(request.url);
if (url.pathname === "/api/messages" && request.method === "POST") {
const body = await request.json().catch(() => ({}));
return Response.json({ ok: true, received: body }, { headers: corsHeaders });
}
return Response.json({ error: "Not found" }, { status: 404, headers: corsHeaders });
},
};
Workers में common mistake है कि headers सिर्फ success path पर लगाए जाते हैं। अगर OPTIONS, 401, 403 या 500 पर CORS headers नहीं हैं, तो DevTools सिर्फ CORS failure दिखा सकता है और असली application error छिप जाती है।
Next.js Route Handler configuration
App Router में app/api/.../route.ts Web standard Request और Response use करता है। Next.js docs response पर CORS headers लगाने का तरीका दिखाते हैं; credentials वाली API के लिए * की जगह allowlist use करें।
// app/api/messages/route.ts
const allowedOrigins = new Set([
"https://app.example.com",
"https://admin.example.com",
"http://localhost:3000",
]);
function getCorsHeaders(request: Request): HeadersInit | null {
const origin = request.headers.get("Origin");
if (!origin) return {};
if (!allowedOrigins.has(origin)) return null;
return {
"Access-Control-Allow-Origin": origin,
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Methods": "POST,OPTIONS",
"Access-Control-Allow-Headers": "Content-Type,Authorization,X-Request-ID",
"Access-Control-Max-Age": "86400",
"Vary": "Origin",
};
}
export async function OPTIONS(request: Request) {
const headers = getCorsHeaders(request);
if (headers === null) {
return Response.json({ error: "Origin not allowed" }, { status: 403 });
}
return new Response(null, { status: 204, headers });
}
export async function POST(request: Request) {
const headers = getCorsHeaders(request);
if (headers === null) {
return Response.json({ error: "Origin not allowed" }, { status: 403 });
}
const body = await request.json().catch(() => ({}));
return Response.json({ ok: true, received: body }, { headers });
}
next.config.js का headers() static public API headers के लिए ठीक है। अगर हर request में origin check करना है, तो Route Handler के अंदर logic ज्यादा readable होता है।
Test commands
curl से preflight और actual request अलग-अलग verify करें। देखें कि Access-Control-Allow-Origin request के Origin से exactly match करता है या नहीं, और Access-Control-Allow-Credentials: true सिर्फ allowed origins के लिए आता है या नहीं।
curl -i -X OPTIONS http://localhost:8787/api/messages \
-H "Origin: http://localhost:3000" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type, Authorization"
curl -i -X POST http://localhost:8787/api/messages \
-H "Origin: http://localhost:3000" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer dev-token" \
--data '{"text":"hello"}'
curl -i -X OPTIONS http://localhost:8787/api/messages \
-H "Origin: https://evil.example" \
-H "Access-Control-Request-Method: POST"
Browser में credentials test ऐसे करें। अगर credentials: "include" है, तो wildcard CORS response browser reject कर देगा।
await fetch("http://localhost:8787/api/messages", {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer dev-token",
},
body: JSON.stringify({ text: "hello" }),
});
Practical use cases
पहला case है SPA और API अलग domains पर। अगर React app https://app.example.com पर है और API https://api.example.com पर, तो explicit allowlist चाहिए। Login cookies हों तो credentials, cookie attributes और CSRF साथ में review करें।
दूसरा case admin frontend है। https://admin.example.com को allowlist में जोड़ सकते हैं, लेकिन CORS को admin permission check न समझें। Authorization logic API code में होना चाहिए।
तीसरा case Cloudflare Worker को BFF या lightweight proxy की तरह use करना है। Browser Worker को call करता है, Worker upstream API को call करता है। Browser को लौटने वाली Worker response पर फिर भी सही CORS headers चाहिए।
चौथा case public read-only API है। अगर cookies, Authorization और private data नहीं हैं, तो Access-Control-Allow-Origin: * acceptable हो सकता है। Future में auth add होने की संभावना हो तो शुरुआत से allowlist रखें।
Specific pitfalls
| Pitfall | Result | Fix |
|---|---|---|
* और credentials: true साथ रखना | Browser response block करता है | Explicit origin return करें |
https://app.example.com/ register करना | Trailing slash match तोड़ता है | https://app.example.com रखें |
सिर्फ localhost allow करना | Different ports fail होते हैं | http://localhost:3000 लिखें |
OPTIONS पर auth require करना | Preflight 401/403 पर रुकता है | Preflight auth से पहले handle करें |
| Error responses पर CORS नहीं | DevTools असली error छिपाता है | 4xx/5xx पर भी headers जोड़ें |
| CDN origin-specific headers cache करता है | Headers mix हो सकते हैं | Vary: Origin जोड़ें |
| CORS को authorization मानना | Non-browser clients फिर भी call करते हैं | Auth, authorization और CSRF अलग implement करें |
MDN साफ कहता है कि credentials वाली CORS request में Access-Control-Allow-Origin: * use नहीं किया जा सकता। अगर Claude Code यह combination generate करे, तो उसे bug मानकर ठीक करें।
Claude Code review prompts
Review this repository's CORS configuration.
Check:
- No Access-Control-Allow-Origin: * when credentials are enabled
- Allowlist uses exact scheme/host/port matching
- OPTIONS preflight runs before authentication middleware
- 4xx/5xx responses include the required CORS headers
- Vary: Origin is present when responses vary by origin
If changes are needed, propose the smallest safe diff.
Diagnose this CORS error by cause.
Browser error:
<paste the full DevTools Console message>
curl preflight:
<paste curl -i -X OPTIONS output>
Expected origin:
https://app.example.com
Read the relevant API files and return reproduction steps, root cause, fix, and tests.
Review the Express/Fastify/Next.js/Workers CORS implementation as a security reviewer.
Focus on:
- Whether request origins are blindly reflected
- Whether localhost remains enabled in production
- Whether Authorization is allowed without proper authorization checks
- Whether cookie flows mention SameSite=None; Secure and CSRF protection
- Whether test commands separate preflight and the real request
Group findings as Critical, Must fix, and Improvement.
Official references और internal links
Specification समझने के लिए MDN CORS guide को base रखें। Implementation के लिए Express cors middleware, @fastify/cors, Cloudflare Workers CORS examples और Next.js Route Handlers देखें। Claude Code workflows के लिए Claude Code commands उपयोगी है।
इसे API development guide, web security headers guide, Cloudflare Workers guide और code review workflow checklist के साथ पढ़ें।
Next step
Sample domains को अपने domains से replace करने के बाद ऊपर वाले review prompts repository पर चलाएँ। फिर Claude Code security best practices से cookies, CSRF, authorization और headers को साथ में review करें। Client project या internal platform में यह checklist review artifact बन सकती है और paid implementation support या reusable templates की proposal में मदद करती है।
असल में test करने का result
Masa के local test में Express और Fastify examples localhost:8787 पर चले; Origin: http://localhost:3000 से preflight और POST सफल रहे, जबकि https://evil.example ने 403 लौटाया। सबसे आसानी से छूटने वाली बातें error responses पर CORS headers और Workers में explicit OPTIONS handling थीं। सबसे stable workflow यह रहा: पहले allowlist implement करें, फिर curl checks चलाएँ, फिर Claude Code से verify कराएँ कि wildcard plus credentials नहीं है, जहाँ जरूरत है वहाँ Vary: Origin है, और localhost production में नहीं जाता।
मुफ़्त PDF: Claude Code cheatsheet
Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.
हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.
लेखक के बारे में
Masa
Claude Code workflow और team adoption पर काम करने वाला engineer.
संबंधित लेख
Claude Code Obsidian to CLAUDE.md workflow: context बार-बार न समझाएं
Obsidian notes को CLAUDE.md operating notes में बदलकर Claude Code sessions को resume करना आसान बनाएं.
Claude Code Revenue CTA Routing: article से PDF, Gumroad और consultation तक
Reader intent के आधार पर free PDF, Gumroad products और consultation तक CTA route करने वाला workflow.
Claude Code टीम हैंडऑफ नियम: review proof, permissions, rollback और revenue path
Claude Code टीम काम के लिए evidence, permission rules, rollback, free PDF, Gumroad और consultation path वाला handoff.