What is Cross Origin Resource Sharing (CORS) ?
About
Cross-origin resource sharing (CORS) 1) is a mechanism that:
- allows a HTTP server
- to control the cross-origin requests executed by a browser.
In short, a HTTP server may allow or not to receive cross-origin requests with or without credentials (ie cookie)
When
This mechanism is used during a browser fetch and:
CORS does not apply to media resources
Motivation / Goal
The main motivation behind Cross-Origin Resource Sharing (CORS) is:
- to remove the same origin restriction from various APIs
- so that resources can be shared among different origins.
Browser vs other Application
This is the browser's responsibility (ie user-agent) to enforce this policy.
A native application (ie not running in the browser) may not bother applying them.
Example / Getting started / Explanation
The article just below explains the basic about the what and the how of CORS. If this is the first time that you encounter a CORS issue, this is a good reading point to start:
Type
Cross-origin HTTP requests are divided into two types:
- simple requests 2)
- and non-simple requests.
Simple
An HTTP request is simple if all of the following conditions are true:
- The request method is:
- If it is a POST method request, it must include an Origin header.
- The request content type is standard ie:
-
- Content-Language
- Last-Event-ID
Simple request does not need the extra authorization request known as preflight or option request.
Non-simple
All cross-origin HTTP requests that are not simple are non-simple requests.
For non-simple request, an extra authorization request known as preflight or options is executed.
Policy
The CORS fetch procedure policy is on a simple level:
- for a simple cors request:
- don't make the extra authorization preflight/option request
- send the request
- check the Cors headers for approval
- for a non-simple cors request
- make the extra authorization preflight/option request
- check the Cors headers for approval
- upon approval, send the request
Below is the complete CORS fetch procedure policy as described by the specification 4)
Preflight request
The Preflight request is an extra authorization request that is executed if the request is not simple.
A Preflight request is a request:
- with OPTIONS method
- with an Origin HTTP header
- that expects a response with only the CORS headers.
The browser checks the headers and upon browser “approval”, the browser sends the actual request with the actual HTTP request method (ie make available to the javascript)
The preflight response may be cached via the access-control-max-age response header
CORS Response Headers
The server sends a response with headers (in all cross request - preflight or not) indicating what is allowed. See Response headers
For instance, the most important is the access-control-allow-origin header that indicates which origin sites are allowed.
For example, if you add the below header to your response, you will allow the page/script of http://www.example.com to make request in the browser against your website.
Access-Control-Allow-Origin: http://www.example.com
Enable
To enable CORS request, you need to set the appropriate response headers via the following possibilities:
- web_server: configuration of the third web server.
- http_server: configuration of your first-party web server generally via a Handler (Middelware).
- a gateway (reverse proxy): configuration of a first-party proxy (that acts as a middle man)
Web Server
Each third application web server has its way to configure the setting of response header for a request.
- In this article, we are showing how to do it for Apache.
- For Nginx and other web server, you can check this web site: https://enable-cors.org/
Http server
If you are developing or using your own http server in your code, you would generally set the CORS Headers via a handler.
- Example with an Express application, allowing cors for local development.
const allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
};
app.use(allowCrossDomain);
- For Vertx, see the dedicated page Vertx - Cors
Proxy
A a gateway (reverse proxy) can be configured to add the cors headers to a response.
Proxy are just http server that acts as a middle-man where the http requests and response transit.
Headers
The HTTP headers that configure the CORS authorization are listed below 5)
Request headers
This is the headers that a preflight_request uses to check what is allowed or not in a cross-origin request.
Origin
The origin request header indicates the origin of the code that want to fetch a resource
Access-Control-Request-Method
Indicates which method a future CORS request to the same resource might use.
Access-Control-Request-Method: POST
Access-Control-Request-Headers
Indicates which headers a future CORS request to the same resource might use.
Response headers
If an URL resource implements CORS, the server needs to define the request property that it will accept (ie
- origins
- HTTP methods
- and type of data
Access-Control-Allow-Origin
Access-Control-Allow-Origin (ACAO) define the allowed origins
- Open to every origin
Access-Control-Allow-Origin: *
- Open only to the origin http://example.com
Access-Control-Allow-Origin: http://example.com
Example of error that you can get:
Origin is not allowed by Access-Control-Allow-Origin No 'Access-Control-Allow-Origin' header is present on the requested resource.
Access-Control-Allow-Credentials
Indicates whether the response can be shared when request’s credentials mode is include.
access-control-allow-credentials: true
Access-Control-Expose-Headers
Give the permission to the code that makes the cross-origin rquest, to list the headers that were set (ie the code knows which header was set but cannot read their value)
Access-Control-Expose-Headers: Content-Type
To give the permission to read the value, see the header access-control-allow-headers
Access-Control-Max-Age
The preflight request is valid and goes into the preflight cache for how many seconds.
Example for 20 days:
Access-Control-Max-Age: 1728000;
Access-Control-Allow-Methods
Which methods are allowed in a cross-origin request
Access-Control-Allow-Methods: PUT, DELETE
Access-Control-Allow-Headers
This header is used in response to the preflight_request which includes the access-control-request-headers to indicate which HTTP headers are allowed by a cross-origin request.
Example
Access-Control-Allow-Headers: x-requested-with, Content-Type, origin, authorization, accept, client-security-token
Support
Response to preflight request doesn't pass access control check
A preflight request is Options request.
Response to preflight request doesn't pass access control check No 'Access-Control-Allow-Origin' header is present
Just add the Access-Control-Allow-Origin to the response. See enable cross request
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'
Failed to load http://api.lavandiere.local/graphql.php: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://docker-host:78' is therefore not allowed access.
No luck
Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
Answer: Configure the server to set the header access-control-allow-headers
Example with apache
Header set Access-Control-Allow-Headers "Content-Type"