CORS
How it works
The browser attaches an Origin header to every cross-origin request. For simple requests — method GET, HEAD or POST, only safelisted headers, and for POST a Content-Type limited to application/x-www-form-urlencoded, multipart/form-data or text/plain — the browser sends the request immediately and then checks whether the response carries a matching Access-Control-Allow-Origin header; if not, it blocks script access to the response. For requests that are not simple (custom headers, other methods, other Content-Type, credentials: include mode) the browser first performs a preflight: an automatic OPTIONS request carrying Access-Control-Request-Method and Access-Control-Request-Headers. The server responds (usually 204) with Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers and optionally Access-Control-Max-Age (preflight cache lifetime). Only after approval is the actual request sent. For credentialed requests (cookies, HTTP auth) the server must return Access-Control-Allow-Credentials: true, and the wildcard "*" is then forbidden for Access-Control-Allow-Origin (and related headers) — an explicit origin must be given, otherwise the browser blocks the response. The Access-Control-Expose-Headers header lists which non-safelisted response headers the script may read.
Problem solved
The Same-Origin Policy blocks reading responses to cross-origin requests made from script, which would prevent legitimate applications (e.g. a frontend on one origin consuming an API on another) from communicating across domains. CORS solves this by letting the server explicitly and selectively grant access to chosen origins — without disabling the browser protection entirely.
Components
Header automatically added by the browser to cross-origin requests; indicates the scheme, host and port of the calling page.
Automatic OPTIONS request sent for non-simple requests, carrying Access-Control-Request-Method and Access-Control-Request-Headers; the server confirms whether the actual request is allowed.
Response header indicating which origin may read the resource: a specific origin or "*"; "*" is forbidden for credentialed requests.
Preflight response header listing the HTTP methods allowed for the resource (e.g. GET, POST, OPTIONS).
Preflight response header listing which headers (e.g. custom ones, Content-Type) may appear in the actual request.
Response header; value true allows including cookies and authentication data. Requires an explicit origin instead of "*".
Response header specifying, in seconds, how long the browser may cache the preflight result, reducing the number of OPTIONS requests.
Response header listing which non-safelisted headers JavaScript may read from the response.
Implementation
When a request includes credentials (credentials: include) and the response has Access-Control-Allow-Origin: *, the browser blocks the response.
The server does not correctly answer the automatic OPTIONS request, so the actual non-simple request is blocked.
Reflecting any Origin into Access-Control-Allow-Origin together with Allow-Credentials: true grants every origin access to resources with the user’s cookies.
Script cannot read non-safelisted response headers unless they are listed in Access-Control-Expose-Headers.
Too short a preflight cache lifetime generates excess OPTIONS requests; browsers also impose their own upper caps.
Evolution
W3C publishes CORS as an official Recommendation (16 January 2014), standardizing the cross-origin access-control headers and the preflight mechanism.
The CORS protocol is folded into the WHATWG Fetch Standard living specification, which now supersedes the W3C document — w3.org/TR/cors redirects to fetch.spec.whatwg.org.
Hyperparameters (configurable axes)
Which origins may read the resource (an explicit list or "*"). With credentials, "*" is not allowed.
HTTP methods allowed for the resource in cross-origin requests.
Request headers (including custom ones) permitted in the actual request.
Whether sending cookies and authentication data is allowed.
How long the browser caches the preflight result.
Which non-safelisted response headers are readable by script.