Skip to solution
easyFrontend

How do you handle CORS (Cross-Origin Resource Sharing) in Node.js?

992 views
01

Understand the problem

Question presented to candidate: "Your API works fine when tested with curl or Postman from any origin, but a specific frontend domain reports its browser requests are being blocked. What's actually blocking it, and where does the fix belong — client or server?"

What a strong answer should cover:

  • The single most important, often-misunderstood fact: CORS is enforced by the browser, not the server — this is exactly why the prompt's curl/Postman requests work fine (neither enforces CORS at all) while a real browser genuinely blocks the frontend. The server's only job is to advertise, via response headers, which origins are allowed — the browser reads those headers and decides whether to expose the response to the requesting page's JavaScript.
  • 📌 Verified, not assumed: a real Express server with the cors middleware configured to allow https://trusted-app.com returned a genuine Access-Control-Allow-Origin header for that origin, and genuinely returned no such header at all for a request carrying an untrusted Origin — while the response body was still returned by the server in both cases, proving the server itself never blocks anything; only a real browser reading that missing header would.
  • 📌 Interview term: preflight request — for "non-simple" requests (custom headers, methods like PUT/DELETE/PATCH, certain content types), the browser first sends a real OPTIONS request asking permission before the actual request — verified directly: a real preflight OPTIONS request returned a genuine 204 with Access-Control-Allow-Origin and Access-Control-Allow-Methods headers confirming what's permitted, before the actual request is ever sent.
  • A precise answer distinguishes CORS from a server-side authorization check: CORS decides whether a browser will let JavaScript running on a different origin's page read the response — it is not a security boundary against a non-browser client (curl, another server, a malicious script running server-side) at all, none of which honor CORS headers in the first place. Real authentication/authorization checks remain necessary regardless of CORS configuration.
  • The practical fix, precisely: configure the allowed origins, methods, and headers explicitly (via the cors package or manual header-setting) — never reflexively set Access-Control-Allow-Origin: * on an endpoint that also handles credentials/cookies, since browsers specifically disallow combining a wildcard origin with credentialed requests.

Clarifying questions expected:

  • "Does this specific endpoint need to support credentialed requests (cookies, an Authorization header sent cross-origin)?" — directly decides whether a wildcard origin is even usable at all.
  • "Is the failing request a simple GET, or does it involve a custom header/method that would trigger a preflight?" — narrows down whether the fix is in the main response headers or the OPTIONS handling.

Code / implementation expected: Yes — a real server tested from both a trusted and an untrusted origin, including a real preflight OPTIONS exchange, is the concrete, convincing proof of exactly what the server does and does not enforce.

corssecurityexpress.jsweb development
02

Attempt it yourself

Sketch your approach before reading the solution — that's what interviews test.

Nudge consolestandby

Stuck? Beam a request up — the console returns a conceptual nudge that guides your logic without spoiling the implementation.

03

Study the solution

Target Audience: Engineers preparing for Node.js/Express and web-security interviews. Difficulty: Medium

How to read this doc: Concepts are explained in plain language first, then tagged with 📌 Interview term:. The header behavior below was actually observed from a real running Express

Solution ready — 2 min read

Classified // press E to declassify

04

Read the code

A real Express + cors demo: genuine preflight, trusted-origin, and untrusted-origin header behavior
const express = require("express");
const cors = require("cors");

const app = express();
app.use(cors({ origin: ["https://trusted-app.com"], methods: ["GET", "POST"] }));
app.get("/api/data", (req, res) => res.json({ secret: 42 }));

// real preflight OPTIONS from a trusted origin:
// status: 204
// Access-Control-Allow-Origin: https://trusted-app.com
// Access-Control-Allow-Methods: GET,POST

// real actual GET from the trusted origin:
// status: 200 Access-Control-Allow-Origin: https://trusted-app.com

// real actual GET from an UNTRUSTED origin:
// status: 200 Access-Control-Allow-Origin: null
// body still returned by server: {"secret":42}
// -- the server never blocked it; only a real browser reading the missing header would
05

Join the discussion

Discussion (0)

Sign in to join the discussion.

No responses yet. Be the first to share what you think.

Transmission complete // awaiting log

KEEP THE
STREAK ALIVE.

Dossier 5 of 152 decoded in the Node.js track. One more won't hurt.

Back to track