CORS checklist

CORS always seems to require more work than I remember, so I made this checklist. Hope it helps!

Satisfying CORS requires browser-side and server-side config.

First, browser-side requirements

The following is required by the browser (not all clients restrict cross-origin resource sharing, only browsers):

  • fetch(url, {mode: 'cors', credentials: 'include'})

    • mode: 'cors' "allows cross-origin requests"

    • credentials: 'include' "send user credentials (cookies, basic http auth, etc..), even for cross-origin"

  • If using cookies for auth token storage, the cookie must have its domain attribute be the same domain as the API you're calling (e.g. cookie's domain is ".example.com" or exact match "api.example.com")

Second, server-side requirements

The following settings are required server-side:

  • Access-Control-Allow-Origin: * is not ideal. It prevents credentials (i.e. "Authorization" and "Cookie" headers) from being sent by the browser. It also means your API accepts requests from everything.

    • Access-Control-Allow-Origin: *.example.com is not supported and neither is a list of origins.

    • Only a single origin can be set, which means your web server has to programmatically figure out if the request is coming from a domain it should support (e.g. compare to a whitelist or regex matcher) and then set the header with that whole origin. (Note: an origin is <scheme>://<hostname> and possibly :<port> if your server exposes that). How to actually do this varies widely depending on your stack, but the result must be a complete origin, like Access-Control-Allow-Origin: https://example.com.

  • Access-Control-Allow-Credentials: true indicates credentials can/should be included.

  • Access-Control-Allow-Methods: <method>[, <method>]* list of HTTP methods to allow. This is used to secure resources from unintended or malicious actions.

The above should get you a working solution. If not, MDN has a really good page on CORS here.