CORS
CORS is a browser mechanism that decides whether JavaScript on origin A may read a response from origin B. An origin is scheme, host, and port. https://app.example.com and https://api.example.com are different origins even though they share a domain.
When the browser asks
Simple requests such as a GET without special headers can go straight through. PUT, DELETE, PATCH, or requests with Content-Type: application/json usually trigger a preflight OPTIONS. The browser asks whether the method and headers are allowed, then sends the real request if the server answers correctly.
The headers involved include Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, and Access-Control-Allow-Credentials. Access-Control-Max-Age controls how long the browser caches the preflight. Add Vary: Origin so a cache does not serve the response for the wrong origin.
`Access
- Control
- Allow
- Origin: *
must not be combined withAccess - Control
- Allow
- Credentials: true`. The browser rejects it. If cookies are used, the server must return the specific origin.
An Nginx example
location /api/ {
add_header Access-Control-Allow-Origin "https://app.example.com" always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Vary "Origin" always;
if ($request_method = OPTIONS) {
return 204;
}
}
With many origins, do not copy all of them into static config without a strategy. Validate the Origin header against an allowlist in the app and echo the matching value.
CORS is not authentication
CORS only constrains browsers. An attacker can call the API from their own server without caring about the header. Keep tokens, sessions, and authorization on the server.
A wildcard is also dangerous when the response contains user data or cookies. Forgetting Vary: Origin lets a CDN serve one origin's response to another. Preflight also fails when the OPTIONS endpoint is auth-protected and demands a token.
For apps that use iframes or third-party widgets, combine CORS with CSP. If the API is opened to a separate frontend, document the allowed origins.
FAQ
Why does a request work in Postman but fail in the browser?
Postman does not enforce the same-origin policy. The browser sends a preflight and checks CORS headers. Fix the server response, not the client app.
Does CORS need to be configured at the CDN?
If the CDN serves an API or assets accessed cross-origin, set headers at the origin and make sure the CDN does not strip Vary: Origin.
Can CORS block server-to-server requests?
No. CORS is a browser rule. Other servers can call your API freely. Use authentication and rate limits to protect it.
Disclaimer: Hosting Wiki articles are prepared for educational and reference purposes. Hosting technology keeps evolving, so some technical details may change over time.