Jon Rumsey

An online markdown blog and knowledge repository.


Project maintained by nojronatron Hosted on GitHub Pages — Theme by mattgraham

Cross Origin Resource Sharing

CORS is a safety feature that restricts certain types of traffic between web apps and servers.

In past projects I have run into CORS-related issues and it has taken lots of time to resolve these.

This reference documentation is meant to be a high-level review of how and why CORS works, with links to references to more detail.

Overview

CORS: Cross Origin Resource Sharing on MDN

Requests That Use CORS

Simple Requests

These do not trigger CORS Preflight checks.

Simple Requests meet the following conditions:

Note: Webkit and Safari have som additional limitations.

Simple Request Example Overview

An XHR might cause browser to send a simple request that will include 'Origin: https://mysite.foo'.

Server might respond 'HTTP/1.1 200 OK' and include 'Access-Control-Allow-Origin: *' which means resource can be accessed by any origin.

If the server wanted to restrict to specific origins it would instead send: 'Access-Control-Allow-Origin: https://mysite.foo'.

Note: Credentialed requests must include a non-wildcard 'Access-Control-Allow-Origin' header response.

Preflighted Requests

See full explanation of access control scenarios at MDN.

Browser sends an HTTP Req using 'OPTIONS'. This asks the server if request is safe to send.

A request might include a custom XHR Header and a 'Content-Type: text/xml' => Both of these make this a Preflighted Request and not a Simple Request.

The server replies with CORS origin URL, allowed methods, the allowed Headers (including allowed custom headers), and an age (expiration).

The client can then be sent to the server, and the Server will send the appropriate response.

Note: 'Access-Control-Request-*' headers are only needed for the OPTIONS request.

Preflight Requests and Redirects

There is lingering behavior in browsers that completely disallows redirects in a Preflight Request type.

To work around this:

If those options are not possible:

Note: Authorization Headers in the request will always trigger Preflight Requests. This means that server-side changes must be made to work around the issue.

Requests with Credentials

Credentials are not sent by default in XHR (request) or Fetch invokations.

XRH must include 'WithCredentials' flag (see code example) to allow cookie-setting by separate URL.

This gets a little complicated. Check out the example on MDN that details what is going on and why.

Preflight Requests with Credentials

Wildcard not allowed in 'Access-Control-Allow-Origin' response header.

Response header must have explicit allow origin list.

Wildcard not allowed in 'Access-Control-Allow-Headers' response header.

Response header must have explicit allow headers list.

Wildcard not allowed in 'Acces-Control-Allow-Methods' response header.

Response header must have explicit allow methods list.

Third Party Cookies

Subject to cookie policies.

HTTP Response Headers

HTTP Request Headers

Key Takeaways: Jake Achibald

See Resources for the blog post where I took these key takeaways:

Adding Credentials

Add credentials back in to CORS requests:

Using "fetch": const response = await fetch(url, { credentials: 'include', }); Using HTML: <img crossorigin="use-credentials" src="" />.

Response must contain access control allow credentials and origin headers as well as 'Vary: Cookie Origin`!

Preflight

Requests that browser API's don't generally make are an 'unusual request' from the perspective of cors.

Request type determines 'usual': GET, HEAD, or POST.

Request headers that are 'unusual': Headers not on a 'safelist'.

Headers Access-Control-Request-Method: ... and Access-Control-Request-Headers: item, item2, ... with a method of Options are sent to the destination URL. No credentials are sent in preflight request.

Preflight server response could be happy or not:

happy:

Access-Control-Max-Age: seconds-in-effect
Access-Control-Allow-Methods: unusual-methods-to-allow
Access-Control-Allow-Headers: unusual-headers-to-allow

FORBIDDEN LIST: Browser-controlled list of headers that are always stripped from cors requests.

Preflight response must pass CORS check so status code must be in 200's and response headers must include:

Access-Control-Allow-Origin
Access-Control-Allow-Credentials: true

Remember: Access-Control-Allow-Credentials means the browser is automatically adding credentials to the request not implemented custom headers!

After Preflight response is received then the actual request can be sent.

The post-preflight request must also pass cors tests or it will be forbidden or ignored.

Note: HTTP Method names might be case sensitive, meaning the browser might require Access-Control-Allow-Methods names to be UPPER-CASED, else they will not pass the check. It is okay to duplicate the method name in Pascal-Case and UPPER-CASE in the same header.

General Notes

Cookie Header can be considered a Credential!

Resources

Cross Origin Resource Sharing on MDN

Web Dev Simplified: CORS in 6 minutes

Jake Archibald's blog page

Return to root README