Browser - Cross Origin Resource Sharing (CORS)

> (World Wide) Web - (W3|WWW) > Web - Browser

1 - About

Cross-origin resource sharing (CORS) is a mechanism that permits cross-origin requests to be executed in the browser.

Specifically, it is a mechanism occurring 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 (i.e. servers).

In this whole procedure, although some validation and authorization can be performed by the server, it is the browser's responsibility to support the below headers and honor the restrictions.

Advertising

3 - Example

Example on how to enable a CORS fetch with the Access-Control-Allow-Origin header from https://jsfiddle.net to this website https://gerardnico.com

Steps:

Header set Access-Control-Allow-Origin "https://fiddle.jshell.net"

$.ajax({
  url: "https://gerardnico.com/doc/api/weather",
  success: function( result ) {
    console.log(result + " degrees" );
  }
});
  • Click on the Try the code on JsFiddle link to see the code on JSFiddle.

  • On the JSFiddle website, you should see the following result:

cors_request_output_on_jsfiddle.jpg

cors_blocked.jpg

Access to XMLHttpRequest at 'https://gerardnico.com/doc/api/weather?zipcode=2343' from origin 'https://fiddle.jshell.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

chrome_network_header_access-control-allow-origin.jpg

Advertising

4 - Request

Below is the CORS fetch procedure described.

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

4.1 - Preflight request

The browser sends the HTTP OPTIONS request with an Origin HTTP header. It's called a preflight request, soliciting supported methods from the server

4.2 - Server answers with supported methods

The server respond with headers 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:

Access-Control-Allow-Origin: http://www.example.com

4.3 - Send actual request

Upon browser “approval”, the browser sends the actual request with the actual HTTP request method (ie make available to the javascript)

5 - Enable

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

Advertising

5.1 - Apache

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

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

5.1.2 - mod_headers

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

6 - Headers

The HTTP headers that relate to CORS are listed below.

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

6.1 - Request headers

6.1.1 - Origin

The origin request header indicates where a fetch originates from.

Access-Control-Allow-Origin: http://localhost:3000

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 domain by the origin

Access-Control-Allow-Origin: *  // Open to every domain
Access-Control-Allow-Origin: http://example.com // Open only to the domain example.com

Example of error that you can get:

Origin is not allowed by Access-Control-Allow-Origin

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

Access-Control-Allow-Headers: Content-Type

6.2.4 - Access-Control-Max-Age

Example htaccess

Header always set Access-Control-Max-Age "1000"

6.2.5 - Access-Control-Allow-Methods

Access-Control-Allow-Methods: PUT, DELETE

Example htaccess

Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"

6.2.6 - Access-Control-Allow-Headers

Indicates which headers are supported by the response’s URL for the purposes of the CORS protocol.

Example htaccess

Header always set 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

preflight request = Options request ?

Response to preflight request doesn't pass access control check No 'Access-Control-Allow-Origin' header is present

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

Header set Access-Control-Allow-Headers "Content-Type"

8 - Documentation / Reference