Browser - Cross Origin Resource Sharing (CORS)

1 - About

Cross-origin resource sharing (CORS) is a protocol that describes how cross-origin requests should be executed in the browser.

This mechanism/protocol is used during a fetch that:

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.

3 - 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:

4 - Policy

Below is the CORS fetch procedure policy described.

Steps (that comes from cors enabled fetch algorithm - Reference):

4.1 - 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

4.2 - 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.

4.3 - 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

5 - Enable

To enable CORS request, you need to set the appropriate headers on the server response via the following possibilities:

5.1 - Apache

To configure cors on a Apache server, you may do it:

5.1.1 - htaccess

  • Apache - htaccess file

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"

5.1.2 - 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>

5.2 - Http server

Http server can set the CORS Headers via a handler.

5.2.1 - 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);

5.2.2 - Vertx

5.3 - Nginx

6 - Headers

The HTTP headers that configure the CORS authorization are listed below.

See documentation at https://fetch.spec.whatwg.org/

6.1 - Request headers

This is the headers that a preflight request uses to check what is allowed or not in a cross-origin request.

6.1.1 - Origin

The origin request header indicates the origin of the code that want to fetch a resource

6.1.2 - Access-Control-Request-Method

Indicates which method a future CORS request to the same resource might use.


Access-Control-Request-Method: POST

6.1.3 - Access-Control-Request-Headers

Indicates which headers a future CORS request to the same resource might use.

6.2 - 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

6.2.1 - Access-Control-Allow-Origin

Access-Control-Allow-Origin (ACAO) define the allowed origins

  • Open to every origin

Access-Control-Allow-Origin: *  


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.

6.2.2 - Access-Control-Allow-Credentials

Indicates whether the response can be shared when request’s credentials mode is include.


access-control-allow-credentials: true

6.2.3 - 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

6.2.4 - 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;

6.2.5 - Access-Control-Allow-Methods

Which methods are allowed in a cross-origin request


Access-Control-Allow-Methods: PUT, DELETE

6.2.6 - 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

7 - Support

7.1 - 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

7.2 - 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

7.3 - 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"

8 - Documentation / Reference


Data Science
Data Analysis
Statistics
Data Science
Linear Algebra Mathematics
Trigonometry

Powered by ComboStrap