Origin-Wide CORS
Editor: Takeshi Yoshino
Introduction
Extra round trip caused by CORS preflight has been adding significant delay to XHR/Fetch with non-simple headers/method. This is preventing performance sensitive applications from adopting web platform.
The Origin-Wide CORS mechanism improves this by allowing an origin server to announce CORS capability and parameters widely across resources.
Design points
Starting with just summarizing ideas proposed at whatwg/fetch#210
- general resource policy setting infra (e.g. CSP) vs. CORS only
- whatwg/fetch#210 (comment)
- mnot's original proposal
- WICG/local-network-access#7
- the address should be under control of the origin's administrator
- hierarchical design or single point
- extend the existing CORS preflight or ...
- Origin-Wide-CORS-Supported: yes
- Merge to Origin-Wide-CORS?
- Origin-Wide-CORS: Origin= ; Headers= ;
- Origin-Wide-CORS-Supported: yes
- patterns
- file fetching + parsing vs. via HTTP headers
- well-known vs. Access-Control-Policy: here
- expiration
- Max-Age
- Etag like versioning?
- scope, realm
- whatwg/fetch#210 (comment)
- each directory vs. subdirectories whatwg/fetch#210 (comment)
- include credentialed or non-credentialed only
- API side switch or internally? whatwg/fetch#210 (comment)
- should allow proxies to cache the CORS information whatwg/fetch#210 (comment)
- resolving inconsistent responses whatwg/fetch#210 (comment)
- policy signing whatwg/fetch#210 (comment)
- JOSE
- JSON, CBOR, ...
Plans
- Start with just allowing for announcing that the origin understands CORS and therefore it's safe to omit preflight. And then, extend it to enable announcing capability in more fine-grained form and detailed parameters
- shouldn't be simply extended to HTTPS from HTTP
- --> Too dangerous? whatwg/fetch#210 (comment)
- Have almost the same level of cumbersomeness as current preflight to prevent people from copy&pasting
Strawman
-
On the initial cross-origin non-simple request to an origin X from origin Y
- The client A issues a preflight request to resource R
- The preflight request MAY include
Origin-Wide-CORS-Supported: yes
header to announce it understands Origin-Wide CORS protocol
- The preflight request MAY include
- If a server B sees the
Origin-Wide-CORS-Supported
header entry in the received CORS preflight or actual CORS request, it MAY include theOrigin-Wide-CORS
header whose value is a Origin-Wide CORS descriptor- The
Origin-Wide-CORS-Supported
header must have either a valueyes
orversion
parameter ortag
parameter - Any entry in the Origin-Wide CORS descriptor whose
url
field is pointing at a resource which is not under R, it must be ignored.
- The
- The client A issues a preflight request to resource R
-
On the initial request to a ...
Origin-Wide-CORS header
The Origin-Wide-CORS
header has a JSON formatted value quoted by quoted-string if needed.
{
"cors": [
{
"url": "/service",
"origin": "http://www.example.com",
"max-age": 31536000,
"credentials": false,
"method": "get",
"headernames": ["x-requested-with", "custom"]
},
...
],
"csp": ...
"upgrade-insecure-requests": ...
}
- This parameter will be stored into the CORS preflight cache with the
origin-wide-cors
flag- Pathes such as "/service", "/service/x", "/service/x/y", "/service/x/y?z=foo", etc. are requested, this cache will be instantiated to a CORS preflight cache entry without the
origin-wide-cors
flag (creates entries for each headername in headernames)- matching is done from the first entry to the last entry
- Partial update is not supported
- The instantiation doesn't happen if there's existing active entry
- Pathes such as "/servicex", "/servicex/y", etc. are not affected.
- Pathes such as "/service", "/service/x", "/service/x/y", "/service/x/y?z=foo", etc. are requested, this cache will be instantiated to a CORS preflight cache entry without the
- Note:
origin
field doesn't support the wildcard "*". A concrete origin must be specified. credentials
defaults to false meaning that thisOrigin-Wide-CORS
parameters affects only non-credentialled requests- The only allowed value for
credentials
is false for the initial version of the protocol - An Origin-Wide-CORS descriptor fetched over HTTP is not applicable to fetches over HTTPS
- An Origin-Wide-CORS descriptor fetched over HTTPS is applicable to fetches over both HTTPS and HTTP
Issues
-
The descriptor gets cached together with the resource R? Separately maintained?
- -> only in response to OPTIONS?
-
Only root considering security concerns?
General Origin-Wide Policy
This protocol can be generalized to allow for announcing various policies in addition to the CORS.
Alternatives
- Standardize how to embed non-simple headers in a URL
- See this post by @wenbozhu
- Foreign fetch ServiceWorker
References
- Well-Known Resources for HTTP OPTIONS: https://mnot.github.io/I-D/http-options-resources/
Acknowledgement
Thanks to Ben Kelly, bifurcation, Jonas Sicking, roryhewitt, Mark Nottingham, Wenbo Zhu.