Build the mental model
Production security is a set of layers, not one setting. HTTPS encrypting traffic in transit is non-negotiable, not optional polish.
- Authentication — who are you (logging in).
- Authorization — what are you allowed to do (permissions after login). Confusing the two is a classic bug source.
- Secrets — passwords, API keys, signing keys — live outside code, in env vars or a secrets manager, never committed.
Least privilege: give every user/service only the permissions it needs. A firewall enforces the network version — open only the ports actually needed.
CORS is not authentication
CORS is a browser-enforced policy on cross-origin requests. It does not protect an API from a non-browser client like a script or curl, which ignores CORS entirely — real auth checks are still required on every endpoint.
Security headers (CSP, HSTS) add browser-enforced protection. IAM — identity, role, permission, policy — is the vendor-neutral framework for who/what can do what.
LAYERED PRODUCTION SECURITY
---------------------------
LAYERED PRODUCTION SECURITY
------------------------------
internet
|
v
+-----------------------------+
| HTTPS (encrypt in transit) |
+-----------------------------+
|
v
+-----------------------------+
| FIREWALL (only needed |
| ports reach the server) |
+-----------------------------+
|
v
+-----------------------------+
| IAM / LEAST PRIVILEGE |
| (what each user/service |
| can do once inside) |
+-----------------------------+
|
v
[ APPLICATION + DATA ]Connect it to a real scenario
CORS enforcement, at its core, checks an incoming Origin header against a list of trusted sites.
An allowed origin gets 'allow' with the origin echoed back as the header. A rejected origin gets 'reject' with no header — telling the browser to block the response.
CORS only matters to browsers
A script or server calling your API directly never sends an Origin header the way a browser does. Real authentication and authorization on every endpoint is still required.
Production Security Basics
Try the working example
function createCorsChecker(allowedOrigins) {
return function checkOrigin(origin) {
const allowed = allowedOrigins.includes(origin);
return {
origin,
decision: allowed ? "allow" : "reject",
headerSent: allowed ? origin : null,
};
};
}
const checkOrigin = createCorsChecker([
"https://app.example.com",
"https://admin.example.com",
]);
console.log(JSON.stringify(checkOrigin("https://app.example.com")));
console.log(JSON.stringify(checkOrigin("https://evil-clone.com")));{"origin":"https://app.example.com","decision":"allow","headerSent":"https://app.example.com"}
{"origin":"https://evil-clone.com","decision":"reject","headerSent":null}5-minute try-it
Add a wildcard subdomain case: allow any origin matching '*.example.com'. Modify createCorsChecker to support it and test with 'https://staging.example.com' and 'https://example.com.evil.com'.
One important caution
Relying on CORS as the only protection for an API endpoint, then discovering a curl request bypasses it entirely.
Granting a service or user broad admin permissions 'to save time' instead of the specific permissions the task actually needs.
MDN — Cross-Origin Resource Sharing (CORS) — Cloud & Deployment