What is Cross Origin Resource Sharing (CORS) ?
Table of Contents
About
Cross-origin resource sharing (CORS) 1) is a protocol that describes how cross-origin requests should be executed by the browser.
This mechanism/protocol is used during a fetch that:
- allows or disallows data resources from an origin
CORS does not apply to media resources
The main motivation behind Cross-Origin Resource Sharing (CORS) was to remove the same origin restriction from various APIs so that resources can be shared among different origins.
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:
Policy
Below is the CORS fetch procedure policy described.
Steps (that comes from cors enabled fetch algorithm - Reference):
Headers
Custom HTTP header are headers that are not:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type
If the cross-origin request has any other headers, a preflight request is executed. Ref
A forbidden header is one of the following
- Accept-Charset
- Accept-Encoding
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Connection
- Content-Length
- Cookie
- Cookie2
- Date
- DNT
- Expect
- Host
- Keep-Alive
- Origin
- Proxy-*
- Referer
- Sec-*
- TE
- Trailer
- Transfer-Encoding
- Upgrade
- Via
Preflight request
The Preflight request is a HTTP OPTIONS request (with an Origin HTTP header) that is sends only in certain situation (see added latency part of the diagram) that expects a response with only the CORS headers.
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.
CORS Response Headers
The server respond 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 headers on the server response via the following possibilities:
- Apache: Configuration of the server.
- http server via a Handler (Middelware).
- A gateway (reverse proxy) that acts as a middle man
Apache
To configure cors on a Apache server, you may do it:
- in a htaccess file
- or via the mod_headers module.
htaccess
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"
mod_headers
- in the Apache configuration file with the mod_headers module enabled.
<!-- for directory -->
<Directory "/path/to/dir">
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
</Directory>
<!-- for specific file -->
<FilesMatch "\.(ttf|otf|eot|woff)$">
<IfModule mod_headers.c>
Header Set Access-Control-Allow-Origin "*"
</IfModule>
</FilesMatch>
<!-- Mutliple Domain -->
<FilesMatch "\.(ttf|otf|eot|woff)$">
<IfModule mod_headers.c>
SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com)$" AccessControlAllowOrigin=$0
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
</IfModule>
</FilesMatch>
Http server
Http server can set the CORS Headers via a handler.
Express
Allowing cors into an Express application 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);
Vertx
Nginx
Headers
The HTTP headers that configure the CORS authorization are listed below.
See documentation at https://fetch.spec.whatwg.org/
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"