Overview
When script on app.example.com fetches api.example.com, the browser sends an Origin header and the server answers with Access-Control-Allow-Origin; on a mismatch the browser hides the response from the script. Configure CORS on the server that returns the data, never on the calling frontend, and list exact origins for any endpoint that uses cookies or tokens. csp is separate: it controls what a page may load, not what it may read.
Rules
- CORS is not authentication or CSRF protection. A simple request still reaches the server; only the response is withheld.
- A request is preflighted (an
OPTIONScall first) when it uses a method other than GET, HEAD, or POST, a custom header, or a non-safelistedContent-Typesuch asapplication/json. The preflight must return 2xx with matchingAccess-Control-Allow-Methodsand-Headers, or the real request is never sent. Access-Control-Allow-Headers: *does not coverAuthorization; list it explicitly. Browsers capAccess-Control-Max-Age(2 hours in Chromium, 24 hours in Firefox).- With credentials,
Access-Control-Allow-Origin: *is rejected. Echo the exact origin from an allowlist, addAccess-Control-Allow-Credentials: true, and sendVary: Origin. - Same-origin APIs, such as a Next.js route handler called by the same app, need no CORS headers.
app.add_middleware(
CORSMiddleware,
allow_origins=["https://myapp.com"],
allow_methods=["GET", "POST"],
allow_headers=["Authorization"],
)Related
- csp: resource-loading policy, a separate mechanism.
- fastapi:
CORSMiddlewaresetup. - nextjs: CORS headers on route handlers.
- http-status-codes: preflight must return 2xx.
- owasp-top-10: where misconfigured CORS fits.