Home > Net >  Why can't I use a wildcard * on Access-Control-Allow-Headers when Allow-Credentials is set to t
Why can't I use a wildcard * on Access-Control-Allow-Headers when Allow-Credentials is set to t

Time:09-18

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:

Firefox error when allow-headers is set to wildcard

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 the Authorization 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, and Access-Control-Allow-Headers response headers, the value * counts as a wildcard for requests without credentials.

Access-Control-Expose-Headers, Access-Control-Allow-Methods, and Access-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 *.

  • Related