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, likeAccess-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.