I have a website where the React frontend resides in (let's say) app.mydomain.com and the api on api.mydomain.com.
The user submits a login request to the API and, upon logging in successfully, receives a nice cookie to be used later. The front-end talks only and directly to the API so the domain on the cookie is simply set to api.mydomain.com.
I use Axios to perform the requests with the withCredentials
flag set to true, in order to receive the cookie.
The headers on the server to allow CORS are as follows:
Access-Control-Allow-Origin: http://app.mydomain.com
Access-Control-Allow-Methods: GET,POST,DELETE,PUT,OPTIONS
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true
In this situation this is the response from Firefox:
But, as soon as the Access-Control-Allow-Headers
value is set more specifically, say to
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
, everything works.
Mozilla says they do not allow "wildcarding" the Origin value, not the Headers one, same in this page, where nothing is mentioned.
Why is Firefox behaving like this and why is it not mentioned anywhere that I can find?
CodePudding user response:
In a preflight response that includes Access-Control-Allow-Credentials: true
, an asterisk used as the value of header Access-Control-Allow-Headers
is interpreted literally, not as a wildcard (i.e. "all headers allowed").
It's true that the main MDN page about CORS doesn't explicitly state this rule. However, the more specific MDN page about the Access-Control-Allow-Headers
header does so explicitly:
The value "
*
" only counts as a special wildcard value for requests without credentials (requests without HTTP cookies or HTTP authentication information). In requests with credentials, it is treated as the literal header name "*
" without special semantics. Note that theAuthorization
header can't be wildcarded and always needs to be listed explicitly.
Here are clarifying quotes from the more authoritative Fetch standard:
For
Access-Control-Expose-Headers
,Access-Control-Allow-Methods
, andAccess-Control-Allow-Headers
response headers, the value*
counts as a wildcard for requests without credentials.
Access-Control-Expose-Headers
,Access-Control-Allow-Methods
, andAccess-Control-Allow-Headers
response headers can only use*
as value when request’s credentials mode is not "include
".
(my emphasis)
The relevant normative requirement for browsers that the spec states is in the main fetch algorithm at https://fetch.spec.whatwg.org/#main-fetch, in step 13, substep 2:
If request's credentials mode is not "
include
" and headerNames contains*
, then set response’s CORS-exposed header-name list to all unique header names in response’s header list.
In other words, the browser behavior that spec statement requires for *
is:
- if the credentials mode is not "
include
", the browser is required to examine the actual list of response headers in the response, and allow all of them - if the credentials mode is "
include
", the browser is required to only allow any response header with the literal name "*
"
At the end of that step, there’s actually a note saying pretty much the same thing:
One of the headerNames can still be
*
at this point, but will only match a header whose name is*
.