CORS (Cross-Origin Resource Sharing)
18 min read
CORSSame-Origin PolicyPre-flightOPTIONSAccess-Control HeadersCredentials
CORS: The Browser's Security Gatekeeper
CORS is not a bug — it's a security feature. It prevents malicious websites from making unauthorized requests to your API using a logged-in user's cookies.
The Same-Origin Policy
Two URLs have the same origin if they share the same protocol + domain + port:
https://app.comandhttps://app.com/api→ Same originhttps://app.comandhttp://app.com→ Different (protocol)https://app.comandhttps://api.app.com→ Different (subdomain)https://app.comandhttps://app.com:8080→ Different (port)
How CORS Works
Simple Requests (No Pre-flight)
GET, HEAD, or POST with simple headers go directly. The browser adds an Origin header, and the server responds with Access-Control-Allow-Origin.
Pre-flight Requests
For "complex" requests (PUT, DELETE, custom headers, JSON content-type), the browser sends an OPTIONS request first:
- Browser sends OPTIONS with
Access-Control-Request-MethodandAccess-Control-Request-Headers - Server responds with allowed methods, headers, and max-age
- If approved, browser sends the actual request
Key Response Headers
| Header | Purpose | Example |
|---|---|---|
| Access-Control-Allow-Origin | Which origins are allowed | https://app.com or * |
| Access-Control-Allow-Methods | Allowed HTTP methods | GET, POST, PUT |
| Access-Control-Allow-Headers | Allowed request headers | Content-Type, Authorization |
| Access-Control-Allow-Credentials | Allow cookies/auth | true |
| Access-Control-Max-Age | Cache pre-flight result | 86400 (24 hours) |
Common Gotcha: Credentials + Wildcard
You cannot use Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true. You must specify the exact origin. This is a frequent source of bugs.