Allow some customizations on CORS configuration
Summary
Allow customizing allowed origins, allow credentials, and max age:
- CORS_ALLOW_ORIGIN:
*(allow any origin),<origin>(which will make it resolve the value from the request'sOriginheader) or a comma-sepparated list of origins, which will make Shlink return the header only when those origins are the ones making the request. Defaults to*. - CORS_ALLOW_CREDENTIALS:
trueorfalse. Defaults tofalse. - CORS_MAX_AGE: Any number representing a value in seconds. Defaults to
3600.
More details:
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Origin
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Credentials
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Max-Age
Use case
This will allow to better support cases like the one described in https://github.com/shlinkio/shlink-web-client/issues/1510
Please note that you will also need to allow the Access-Control-Allow-Headers header to be configured.
Per MDN:
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.
Please note that you will also need to allow the Access-Control-Allow-Headers header to be configured.
I will verify it, but I would expect this to cover for anything https://github.com/shlinkio/shlink/blob/develop/module/Rest/src/Middleware/CrossDomainMiddleware.php#L42
That basically means Shlink will set the value of Access-Control-Allow-Headers based on what the browser set in Access-Control-Request-Headers.
It's always better if it can be made so that there's less room for human error.
~~Unfortunately I think that's not enough. The problem is that the preflight request happens before those headers are sent, because the client doesn't know that it's okay to send them yet. So they're not included in the preflight request, the preflight response doesn't know to say "yes, those headers are okay", and then the browser fails to send the actual request because the headers it was asked to provide weren't whitelisted by the preflight.~~
~~I think in your mental model, the browser sends all the headers it hopes to send as part of the initial CORS preflight, the preflight response says "yes, those are okay", and then the browser makes the actual request with those headers. But instead, the client makes a request without any of those headers, the server explicitly tells the client which ones are okay to send, and then the client decides whether or not it can make the request based on the headers it needs to include.~~
One sec, I think something else is going on for us. You're right that the browser should include all of the headers in the original request, in the Access-Control-Request-Headers header. Sorry, CORS is quite complex in practice.
Sorry, CORS is quite complex in practice.
It's a pain in the ass 😅
This feature is now implemented.
Three new options are now available:
-
CORS_MAX_AGE: determines the value of theAccess-Control-Max-Ageheader. -
CORS_ALLOW_CREDENTIALS: setsAccess-Control-Allow-Credentials: truewhen it istrue.Access-Control-Allow-Credentialsis not set at all otherwise. -
CORS_ALLOW_ORIGIN:- When it is
*it setsAccess-Control-Allow-Origin: *. - When it has the special value
<origin>, it sets the value on the request'sOriginheader as the response'sAccess-Control-Allow-Origin. - When a comma-separated list of values is set, it sets the value on the request's
Originheader as the response'sAccess-Control-Allow-Origin, only of the value is is part of that list. Otherwise,Access-Control-Allow-Originis not set at all.
- When it is