Cross-Origin Resource Sharing (CORS)
Cross-Origin Resource Sharing (CORS) is the server-controlled protocol that allows a browser to relax the Same-Origin Policy (SOP) when the response explicitly whitelists the calling origin. It can feel like a productivity killer during development, but CORS is simply the browser confirming that a remote API actually trusts your front-end before handing you sensitive data.
Mechanism: Simple vs. Preflight Requests
Browsers categorize cross-origin requests into two types so they can decide how much validation is required.
1. Simple Requests
A request qualifies as “simple” if it meets the W3C criteria: it uses GET, HEAD, or POST and only includes standard headers (Accept, Accept-Language, Content-Type with text/plain, multipart/form-data, or application/x-www-form-urlencoded). The browser sends these requests directly and then inspects the response headers to see if the origin was allowed.
2. Preflight Requests
If the request involves potentially sensitive operations—PUT, DELETE, custom headers, JSON bodies—the browser performs a preflight check. It sends an automatic OPTIONS request asking the server for permission before the actual call:
OPTIONS /api/resource
Origin: https://app.example.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: Authorization, X-Trace-Id- The Check: the browser asks, “May I send this method/headers from this origin?”
- The Response: the server must reply with explicit
Access-Control-Allow-*headers. If the origin or method isn’t whitelisted, the browser blocks the real request.
Essential HTTP Response Headers
A correct CORS implementation relies on specific headers in the server’s response:
Access-Control-Allow-Origin— Lists the origin(s) permitted to read the response.Access-Control-Allow-Methods— Enumerates the HTTP methods allowed for that origin.Access-Control-Allow-Headers— Indicates which custom headers the client may send.Access-Control-Allow-Credentials— Boolean flag telling the browser whether cookies/Authorization headers may accompany the request.Access-Control-Max-Age— Duration (in seconds) that the browser may cache the preflight approval, reducing round-trips.
Security Implications and Best Practices
Misconfigured CORS can open serious holes. Treat the headers as part of your security architecture:
- Avoid wildcard origins in production.
Access-Control-Allow-Origin: *is fine for anonymous, public APIs. Authenticated or internal endpoints must list the exact origin they trust. - Handle credentials carefully. When
Access-Control-Allow-Credentials: trueis present, theAllow-Originheader cannot be a wildcard; it must explicitly echo the calling origin. - Minimize preflight latency. Use
Access-Control-Max-Ageso the browser can cache the preflight response and avoid extraOPTIONSrequests.
Note
CORS is browser-side only. curl, Postman, Node servers, Lambda functions—all bypass SOP/CORS entirely. Protect sensitive APIs with real authentication and authorization (OAuth2, JWTs, mTLS, VPNs, IP allowlists).