A quick introduction to CORS
Cross-Site Request Forgery (CSRF) is an attack pattern for websites. A CSRF attack is usually relevant in a browser context, where state is kept for multiple domains (as opposed to independent requests made e.g. with
curl). The most common example is authentication via cookies. If a script on
https://example.com made requests to
https://docs.google.com, the browser would send all cookies for docs.google.com along, effectively given the script access to anything the user has access to. This is a huge security issue.
The Same-Origin Policy (SOP) is a counter-measure for CSRF. It states that scripts in a web page may only access data from the same origin and is implemented by virtually any browser since the 90s. By blocking any cross-site or cross-domain interaction, it mitigates most of the CSRF danger. "Origin" in this context is defined as protocol + hostname + port of the current URL. Example: an AJAX request to
https://docs.google.com:443 will not succeed when performed by a script on
Note that common CSRF attacks or countermeasures are different from the CSRF description above. This is because SOP mitigates the described straight-forward attack and requires attackers to concoct more complex attacks, which in turn requires CSRF-Tokens and the like.
Cross-Origin Resource Sharing
With SOP, we're safe from unwanted cross-origin interaction – but we cannot even intentionally cross the origin border. Sometimes this is necessary, e.g. to access an API that has been moved to its own domain.
Over time, there have been a few approaches to achieve this (
window.postMessage), of which CORS is the youngest. Cross-Origin Resource Sharing is a strategy to manually enable certain origins to interchange data. Because CSRF exploits browser behavior, its mitigation CORS is also implemented by browsers.
The CORS workflow is basically this: When the browser is told to make a CORS request, it adds an
Origin: header with the origin (protocol + hostname + port). The server decides whether access is acceptable for this origin and adds the
Access-Control-Allow-Origin: header to the response. If the header contains the origin (or "*" for "any"), the response is processed. If not, it is discarded. This way, CORS puts cross-domain access control in the hands of the requested server.
Certain request types (mostly non-GET requests) require a special "preflight" request that checks server approval upfront. These requests are performed with the HTTP verb
OPTIONS. Only when the ACAO header permits access, the normal request is performed. This is a security measure to prevent unauthorized state or data modification.
Allowing multiple origins
The ACAO header can only contain a single value. In order to allow a whitelist of origins, the server must check incoming requests against a list internally, and if allowed, set the ACAO header with the value of
Fonts and CORS
In contrast to images/videos/etc, web fonts are subject to SOP and thus require an ACAO header to be used on a different domain.