Cross-Origin Resource Sharing (CORS) is a browser security mechanism that blocks JavaScript from reading responses to cross-origin requests unless the server opts in with Access-Control-* headers; a credentialed request (cookies or Authorization) additionally requires an explicit origin and a credentials allowance.
In simpler words
CORS is the browser rule that stops a random site from reading your API’s responses — the server has to say “this origin is allowed, and yes it may send cookies”.
In a Nest API, CORS is typically enabled from a CORS_ORIGIN env value with credentials: true, which is exactly what an httpOnly-cookie auth flow needs.
Read a typical enableCors config and the CORS_ORIGIN env
Say why credentials: true cannot be paired with a wildcard origin
What CORS is (and what it is not)
Definition
CORS relaxes the browser’s same-origin policy by letting a server declare which other origins may read its responses; it is enforced by the browser on the response, not by the server on the request, and it is not authentication or a firewall.
In simpler words
CORS decides whether the browser lets page JavaScript read your response — it does not stop curl, Postman, or a server from calling you.
Same-origin policy blocks a page on origin A from reading responses from origin B by default; CORS headers are how origin B says that A is allowed.
Non-browser clients ignore CORS entirely — it protects users in browsers, so never mistake it for access control. Authorization still lives in the Nest guards.
Why the browser blocks by default
// Page at http://localhost:3000 calls the API at http://localhost:3001
fetch('http://localhost:3001/tickets', { credentials: 'include' });
// Blocked unless the API returns:
// Access-Control-Allow-Origin: http://localhost:3000
// Access-Control-Allow-Credentials: true
Without those response headers the request may still reach Nest, but the browser refuses to let the page read the result.
A typical CORS config, and the cookie pairing
Definition
A typical setup parses CORS_ORIGIN into an allowed-origin list and calls app.enableCors with credentials: true, which is the precise combination required for the browser to send and accept the httpOnly access_token cookie on cross-origin requests.
In simpler words
The frontend on :3000 talks to Nest on :3001, so cookies only flow because Nest allows that exact origin and allows credentials.
A common pattern splits CORS_ORIGIN on commas, trims blanks, and passes a single string or an array to enableCors with credentials: true.
The pairing is two-sided: the browser fetch/axios call must include credentials (the FE axios-nest-cookies topic) and Nest must set credentials: true — miss either and the cookie is silently dropped.
CORS_ORIGIN is env-driven so dev (localhost:3000) and production origins differ without code changes.
Wildcards, preflight, and common mistakes
Definition
The CORS spec forbids combining a wildcard origin with credentials, so a credentialed API must echo a specific allowed origin; browsers also send a preflight OPTIONS request for non-simple requests, which the server must answer with the matching allow headers.
In simpler words
You cannot say “allow everyone” and “allow cookies” at once, and the browser’s pre-check (OPTIONS) has to pass before the real request runs.
A wildcard origin combined with credentials: true is rejected by the browser — list the real origins instead, which is why CORS_ORIGIN is a concrete allow-list here.
A preflight is an automatic OPTIONS request the browser sends for methods or headers beyond the simple set; enableCors answers it, but a custom header your client sends must be in the allowed headers or the preflight fails.
Mistake: wildcard with credentials
// Wrong — browser refuses this combination
app.enableCors({ origin: '*', credentials: true });
// Right — specific origin(s) + credentials
app.enableCors({ origin: ['https://app.example.com'], credentials: true });
With credentials, the response must name an exact origin; a wildcard is only valid for non-credentialed requests.
Keep in mind
Treat CORS as a browser read-protection, never as authorization.
Keep the allow-list in CORS_ORIGIN env — no hardcoded origins across environments.
credentials: true requires a specific origin and a client sending credentials — set both sides.
When a cross-origin call fails, check the preflight OPTIONS response first.
Test
Check your understanding
At least 10 questions — mix of concept, syntax, practical, and logic. Score ≥80% (enforced by the API) to save progress.