Movatterモバイル変換


[0]ホーム

URL:


  1. Web
  2. HTTP
  3. Guides
  4. Cross-Origin Resource Sharing (CORS)

Cross-Origin Resource Sharing (CORS)

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since ⁨July 2015⁩.

Cross-Origin Resource Sharing (CORS) is anHTTP-header based mechanism that allows a server to indicate anyorigins (domain, scheme, or port) other than its own from which a browser should permit loading resources. CORS also relies on a mechanism by which browsers make a "preflight" request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request.

An example of a cross-origin request: the front-end JavaScript code served fromhttps://domain-a.com usesfetch() to make a request forhttps://domain-b.com/data.json.

For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts. For example,fetch() andXMLHttpRequest follow thesame-origin policy. This means that a web application using those APIs can only request resources from the same origin the application was loaded from unless the response from other origins includes the right CORS headers.

Diagrammatic representation of CORS mechanism

The CORS mechanism supports secure cross-origin requests and data transfers between browsers and servers. Browsers use CORS in APIs such asfetch() orXMLHttpRequest to mitigate the risks of cross-origin HTTP requests.

What requests use CORS?

Thiscross-origin sharing standard can enable cross-origin HTTP requests for:

  • Invocations offetch() orXMLHttpRequest, as discussed above.
  • Web Fonts (for cross-domain font usage in@font-face within CSS), as described in thefont fetching requirements, so that servers can deploy TrueType fonts that can only be loaded cross-origin and used by websites that are permitted to do so.
  • WebGL textures.
  • Images/video frames drawn to a canvas usingdrawImage().
  • CSS Shapes from images.

This is a general article about Cross-Origin Resource Sharing and includes a discussion of the necessary HTTP headers.

Functional overview

The Cross-Origin Resource Sharing standard works by adding newHTTP headers that let servers describe which origins are permitted to read that information from a web browser. Additionally, for HTTP request methods that can cause side-effects on server data (in particular, HTTP methods other thanGET, orPOST with certainMIME types), the specification mandates that browsers "preflight" the request, soliciting supported methods from the server with the HTTPOPTIONS request method, and then, upon "approval" from the server, sending the actual request. Servers can also inform clients whether "credentials" (such asCookies andHTTP Authentication) should be sent with requests.

CORS failures result in errors but for security reasons, specifics about the errorare not available to JavaScript. All the code knows is that an error occurred. The only way to determine what specifically went wrong is to look at the browser's console for details.

Subsequent sections discuss scenarios, as well as provide a breakdown of the HTTP headers used.

Examples of access control scenarios

We present three scenarios that demonstrate how Cross-Origin Resource Sharing works. All these examples usefetch(), which can make cross-origin requests in any supporting browser.

Simple requests

Some requests don't trigger aCORS preflight. Those are calledsimple requests from the obsoleteCORS spec, though theFetch spec (which now defines CORS) doesn't use that term.

The motivation is that the<form> element from HTML 4.0 (which predates cross-sitefetch() andXMLHttpRequest) can submit simple requests to any origin, so anyone writing a server must already be protecting againstcross-site request forgery (CSRF). Under this assumption, the server doesn't have to opt-in (by responding to a preflight request) to receive any request that looks like a form submission, since the threat of CSRF is no worse than that of form submission. However, the server still must opt-in usingAccess-Control-Allow-Origin toshare the response with the script.

Asimple request is one thatmeets all the following conditions:

Note:WebKit Nightly and Safari Technology Preview place additional restrictions on the values allowed in theAccept,Accept-Language, andContent-Language headers. If any of those headers have "nonstandard" values, WebKit/Safari does not consider the request to be a "simple request". What values WebKit/Safari consider "nonstandard" is not documented, except in the following WebKit bugs:

No other browsers implement these extra restrictions because they're not part of the spec.

For example, suppose web content athttps://foo.example wishes to fetch JSON content from domainhttps://bar.other. Code of this sort might be used in JavaScript deployed onfoo.example:

js
const fetchPromise = fetch("https://bar.other");fetchPromise  .then((response) => response.json())  .then((data) => {    console.log(data);  });

This operation performs a simple exchange between the client and the server, using CORS headers to handle the privileges:

Diagram of simple CORS GET request

Let's look at what the browser will send to the server in this case:

http
GET /resources/public-data/ HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateConnection: keep-aliveOrigin: https://foo.example

The request header of note isOrigin, which shows that the invocation is coming fromhttps://foo.example.

Now let's see how the server responds:

http
HTTP/1.1 200 OKDate: Mon, 01 Dec 2008 00:23:53 GMTServer: Apache/2Access-Control-Allow-Origin: *Keep-Alive: timeout=2, max=100Connection: Keep-AliveTransfer-Encoding: chunkedContent-Type: application/xml[…XML Data…]

In response, the server returns anAccess-Control-Allow-Origin header withAccess-Control-Allow-Origin: *, which means that the resource can be accessed byany origin.

http
Access-Control-Allow-Origin: *

This pattern of theOrigin andAccess-Control-Allow-Origin headers is the simplest use of the access control protocol. If the resource owners athttps://bar.other wished to restrict access to the resource to requestsonly fromhttps://foo.example (i.e., no domain other thanhttps://foo.example can access the resource in a cross-origin manner), they would send:

http
Access-Control-Allow-Origin: https://foo.example

Note:When responding to acredentialed requests request, the servermust specify an origin in the value of theAccess-Control-Allow-Origin header, instead of specifying the* wildcard.

Preflighted requests

Unlikesimple requests, for "preflighted" requests the browser first sends an HTTP request using theOPTIONS method to the resource on the other origin, in order to determine if the actual request is safe to send. Such cross-origin requests are preflighted since they may have implications for user data.

The following is an example of a request that will be preflighted:

js
const fetchPromise = fetch("https://bar.other/doc", {  method: "POST",  mode: "cors",  headers: {    "Content-Type": "text/xml",    "X-PINGOTHER": "pingpong",  },  body: "<person><name>Arun</name></person>",});fetchPromise.then((response) => {  console.log(response.status);});

The example above creates an XML body to send with thePOST request. Also, a non-standard HTTPX-PINGOTHER request header is set. Such headers are not part of HTTP/1.1, but are generally useful to web applications. Since the request uses aContent-Type oftext/xml, and since a custom header is set, this request is preflighted.

Diagram of a request that is preflighted

Note:As described below, the actualPOST request does not include theAccess-Control-Request-* headers; they are needed only for theOPTIONS request.

Let's look at the full exchange between client and server. The first exchange is thepreflight request/response:

http
OPTIONS /doc HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateConnection: keep-aliveOrigin: https://foo.exampleAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: content-type,x-pingotherHTTP/1.1 204 No ContentDate: Mon, 01 Dec 2008 01:15:39 GMTServer: Apache/2Access-Control-Allow-Origin: https://foo.exampleAccess-Control-Allow-Methods: POST, GET, OPTIONSAccess-Control-Allow-Headers: X-PINGOTHER, Content-TypeAccess-Control-Max-Age: 86400Vary: Accept-Encoding, OriginKeep-Alive: timeout=2, max=100Connection: Keep-Alive

The first block above represents the preflight request with theOPTIONS method. The browser determines that it needs to send this based on the request parameters that the JavaScript code snippet above was using, so that the server can respond whether it is acceptable to send the request with the actual request parameters. OPTIONS is an HTTP/1.1 method that is used to determine further information from servers, and is asafe method, meaning that it can't be used to change the resource. Note that along with the OPTIONS request, two other request headers are sent:

http
Access-Control-Request-Method: POSTAccess-Control-Request-Headers: content-type,x-pingother

TheAccess-Control-Request-Method header notifies the server as part of a preflight request that when the actual request is sent, it will do so with aPOST request method. TheAccess-Control-Request-Headers header notifies the server that when the actual request is sent, it will do so withX-PINGOTHER andContent-Type custom headers. Now the server has an opportunity to determine whether it can accept a request under these conditions.

The second block above is the response that the server returns, which indicate that the request method (POST) and request headers (X-PINGOTHER) are acceptable. Let's have a closer look at the following lines:

http
Access-Control-Allow-Origin: https://foo.exampleAccess-Control-Allow-Methods: POST, GET, OPTIONSAccess-Control-Allow-Headers: X-PINGOTHER, Content-TypeAccess-Control-Max-Age: 86400

The server responds withAccess-Control-Allow-Origin: https://foo.example, restricting access to the requesting origin domain only. It also responds withAccess-Control-Allow-Methods, which says thatPOST andGET are valid methods to query the resource in question (this header is similar to theAllow response header, but used strictly within the context of access control).

The server also sendsAccess-Control-Allow-Headers with a value ofX-PINGOTHER, Content-Type, confirming that these are permitted headers to be used with the actual request. LikeAccess-Control-Allow-Methods,Access-Control-Allow-Headers is a comma-separated list of acceptable headers.

Finally,Access-Control-Max-Age gives the value in seconds for how long the response to the preflight request can be cached without sending another preflight request. The default value is 5 seconds. In the present case, the max age is 86400 seconds (= 24 hours). Note that each browser has amaximum internal value that takes precedence when theAccess-Control-Max-Age exceeds it.

Once the preflight request is complete, the real request is sent:

http
POST /doc HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateConnection: keep-aliveX-PINGOTHER: pingpongContent-Type: text/xml; charset=UTF-8Referer: https://foo.example/examples/preflightInvocation.htmlContent-Length: 55Origin: https://foo.examplePragma: no-cacheCache-Control: no-cache<person><name>Arun</name></person>HTTP/1.1 200 OKDate: Mon, 01 Dec 2008 01:15:40 GMTServer: Apache/2Access-Control-Allow-Origin: https://foo.exampleVary: Accept-Encoding, OriginContent-Encoding: gzipContent-Length: 235Keep-Alive: timeout=2, max=99Connection: Keep-AliveContent-Type: text/plain[Some XML content]

Preflighted requests and redirects

Not all browsers currently support following redirects after a preflighted request. If a redirect occurs after such a request, some browsers currently will report an error message such as the following:

The request was redirected tohttps://example.com/foo, which is disallowed for cross-origin requests that require preflight.Request requires preflight, which is disallowed to follow cross-origin redirects.

The CORS protocol originally required that behavior butwas subsequently changed to no longer require it. However, not all browsers have implemented the change, and thus still exhibit the originally required behavior.

Until browsers catch up with the spec, you may be able to work around this limitation by doing one or both of the following:

  • Change the server-side behavior to avoid the preflight and/or to avoid the redirect
  • Change the request such that it is asimple request that doesn't cause a preflight

If that's not possible, then another way is to:

  1. Make asimple request (usingResponse.url for the Fetch API, orXMLHttpRequest.responseURL) to determine what URL the real preflighted request would end up at.
  2. Make another request (thereal request) using the URL you obtained fromResponse.url orXMLHttpRequest.responseURL in the first step.

However, if the request is one that triggers a preflight due to the presence of theAuthorization header in the request, you won't be able to work around the limitation using the steps above. And you won't be able to work around it at all unless you have control over the server the request is being made to.

Requests with credentials

Note:When making credentialed requests to a different domain, third-party cookie policies will still apply. The policy is always enforced regardless of any setup on the server and the client as described in this chapter.

The most interesting capability exposed by bothfetch() orXMLHttpRequest and CORS is the ability to make "credentialed" requests that are aware ofHTTP cookies and HTTP Authentication information. By default, in cross-originfetch() orXMLHttpRequest calls, browsers willnot send credentials.

To ask for afetch() request to include credentials, set thecredentials option to"include".

To ask for anXMLHttpRequest request to include credentials, set theXMLHttpRequest.withCredentials property totrue.

In this example, content originally loaded fromhttps://foo.example makes a GET request to a resource onhttps://bar.other which sets Cookies. Content on foo.example might contain JavaScript like this:

js
const url = "https://bar.other/resources/credentialed-content/";const request = new Request(url, { credentials: "include" });const fetchPromise = fetch(request);fetchPromise.then((response) => console.log(response));

This code creates aRequest object, setting thecredentials option to"include" in the constructor, then passes this request intofetch(). Since this is a simpleGET request, it is not preflighted but the browser willreject any response that does not have theAccess-Control-Allow-Credentials header set totrue, andnot make the response available to the invoking web content.

Diagram of a GET request with Access-Control-Allow-Credentials

Here is a sample exchange between client and server:

http
GET /resources/credentialed-content/ HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateConnection: keep-aliveReferer: https://foo.example/examples/credential.htmlOrigin: https://foo.exampleCookie: pageAccess=2HTTP/1.1 200 OKDate: Mon, 01 Dec 2008 01:34:52 GMTServer: Apache/2Access-Control-Allow-Origin: https://foo.exampleAccess-Control-Allow-Credentials: trueCache-Control: no-cachePragma: no-cacheSet-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMTVary: Accept-Encoding, OriginContent-Encoding: gzipContent-Length: 106Keep-Alive: timeout=2, max=100Connection: Keep-AliveContent-Type: text/plain[text/plain content]

Although the request'sCookie header contains the cookie destined for the content onhttps://bar.other, if bar.other did not respond with anAccess-Control-Allow-Credentials with valuetrue, as demonstrated in this example, the response would be ignored and not made available to the web content.

Preflight requests and credentials

CORS-preflight requests must never include credentials. Theresponse to a preflight request must specifyAccess-Control-Allow-Credentials: true to indicate that the actual request can be made with credentials.

Note:Some enterprise authentication services require that TLS client certificates be sent in preflight requests, in contravention of theFetch specification.

Firefox 87 allows this non-compliant behavior to be enabled by setting the preference:network.cors_preflight.allow_client_cert totrue (Firefox bug 1511151). Chromium-based browsers currently always send TLS client certificates in CORS preflight requests (Chrome bug 775438).

Credentialed requests and wildcards

When responding to a credentialed request:

  • The servermust not specify the* wildcard for theAccess-Control-Allow-Origin response-header value, but must instead specify an explicit origin; for example:Access-Control-Allow-Origin: https://example.com
  • The servermust not specify the* wildcard for theAccess-Control-Allow-Headers response-header value, but must instead specify an explicit list of header names; for example,Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
  • The servermust not specify the* wildcard for theAccess-Control-Allow-Methods response-header value, but must instead specify an explicit list of method names; for example,Access-Control-Allow-Methods: POST, GET
  • The servermust not specify the* wildcard for theAccess-Control-Expose-Headers response-header value, but must instead specify an explicit list of header names; for example,Access-Control-Expose-Headers: Content-Encoding, Kuma-Revision

If a request includes a credential (most commonly aCookie header) and the response includes anAccess-Control-Allow-Origin: * header (that is, with the wildcard), the browser will block access to the response, and report a CORS error in the devtools console.

But if a request does include a credential (like theCookie header) and the response includes an actual origin rather than the wildcard (like, for example,Access-Control-Allow-Origin: https://example.com), then the browser will allow access to the response from the specified origin.

Also note that anySet-Cookie response header in a response would not set a cookie if theAccess-Control-Allow-Origin value in that response is the* wildcard rather an actual origin.

Third-party cookies

Note that cookies set in CORS responses are subject to normal third-party cookie policies. In the example above, the page is loaded fromfoo.example but theSet-Cookie header in the response is sent bybar.other, and would thus not be saved if the user's browser is configured to reject all third-party cookies.

Cookies set in CORS requests and responses are subject to normal third-party cookie policies.

Third-party cookie policies may prevent third party cookies being sent in requests, effectively stopping a site from making credentialed requests even if permitted by the third party server (usingAccess-Control-Allow-Credentials).The default policy differs between browsers, but may be set using theSameSite attribute.

Even if credentialed requests are allowed, a browser may be configured to reject all third-party cookies in responses.

The HTTP response headers

This section lists the HTTP response headers that servers return for access control requests as defined by the Cross-Origin Resource Sharing specification. The previous section gives an overview of these in action.

Access-Control-Allow-Origin

A returned resource may have oneAccess-Control-Allow-Origin header with the following syntax:

http
Access-Control-Allow-Origin: <origin> | *

Access-Control-Allow-Origin specifies either a single origin which tells browsers to allow that origin to access the resource; or else — for requestswithout credentials — the* wildcard tells browsers to allow any origin to access the resource.

For example, to allow code from the originhttps://mozilla.org to access the resource, you can specify:

http
Access-Control-Allow-Origin: https://mozilla.orgVary: Origin

If the server specifies a single origin (that may dynamically change based on the requesting origin as part of an allowlist) rather than the* wildcard, then the server should also includeOrigin in theVary response header to indicate to clients that server responses will differ based on the value of theOrigin request header.

Access-Control-Expose-Headers

TheAccess-Control-Expose-Headers header adds the specified headers to the allowlist that JavaScript (such asResponse.headers) in browsers is allowed to access.

http
Access-Control-Expose-Headers: <header-name>[, <header-name>]*

For example, the following would allow theX-My-Custom-Header andX-Another-Custom-Header headers to be exposed to the browser:

http
Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header

Access-Control-Max-Age

TheAccess-Control-Max-Age header indicates how long the results of a preflight request can be cached. For an example of a preflight request, see the above examples.

http
Access-Control-Max-Age: <delta-seconds>

Thedelta-seconds parameter indicates the number of seconds the results can be cached.

Access-Control-Allow-Credentials

TheAccess-Control-Allow-Credentials header indicates whether or not the response to the request can be exposed when thecredentials flag is true. When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials. Note that simpleGET requests are not preflighted, and so if a request is made for a resource with credentials, if this header is not returned with the resource, the response is ignored by the browser and not returned to web content.

http
Access-Control-Allow-Credentials: true

Credentialed requests are discussed above.

Access-Control-Allow-Methods

TheAccess-Control-Allow-Methods header specifies the method or methods allowed when accessing the resource. This is used in response to a preflight request. The conditions under which a request is preflighted are discussed above.

http
Access-Control-Allow-Methods: <method>[, <method>]*

An example of apreflight request is given above, including an example which sends this header to the browser.

Access-Control-Allow-Headers

TheAccess-Control-Allow-Headers header is used in response to apreflight request to indicate which HTTP headers can be used when making the actual request. This header is the server side response to the browser'sAccess-Control-Request-Headers header.

http
Access-Control-Allow-Headers: <header-name>[, <header-name>]*

The HTTP request headers

This section lists headers that clients may use when issuing HTTP requests in order to make use of the cross-origin sharing feature. Note that these headers are set for you when making invocations to servers. Developers making cross-origin requests do not have to set any cross-origin sharing request headers programmatically.

Origin

TheOrigin header indicates the origin of the cross-origin access request or preflight request.

http
Origin: <origin>

The origin is a URL indicating the server from which the request is initiated. It does not include any path information, only the server name.

Note:Theorigin value can benull.

Note that in any access control request, theOrigin header isalways sent.

Access-Control-Request-Method

TheAccess-Control-Request-Method is used when issuing a preflight request to let the server know what HTTP method will be used when the actual request is made.

http
Access-Control-Request-Method: <method>

Examples of this usage can befound above.

Access-Control-Request-Headers

TheAccess-Control-Request-Headers header is used when issuing a preflight request to let the server know what HTTP headers will be used when the actual request is made (for example, by passing them as theheaders option). This browser-side header will be answered by the complementary server-side header ofAccess-Control-Allow-Headers.

http
Access-Control-Request-Headers: <field-name>[,<field-name>]*

Examples of this usage can befound above.

Specifications

Specification
Fetch
# http-access-control-allow-origin

Browser compatibility

See also

Help improve MDN

Learn how to contribute

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp