Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any other origins (domain, scheme, or port) than its own from which a browser should permit loading of 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.
XMLHttpRequest
and the Fetch API
follow the same-origin policy means that a web application can only request resources from the same origin the application was loaded from unless the response from other origins includes the right CORS headers.
Origin = scheme + host + port
Cross-Origin means a request sent from A origin to B origin.
For example, http://localhost:3000 sends a request to http://localhost:3001.
- Bob sets up a malicious website, https://bob.com, which wants to access http://localhost:8888.
- Alice opens her browser and access https://bob.com.
- If there is no CORS restriction, Bob's website can get information from Alice's http://localhost:8888.
- Bob's website sends the information from Alice's http://localhost:8888 to his own server.
As the above example described, if there is no Same-Origin Policy and CORS, Bob is able to get anyone's private information.
Follow CORS!
CORS is a part of HTTP that lets servers specify any other hosts from which a browser should permit loading of content.
Browser!
Javascript code of a web is running on browser.
Browser blocks the response NOT the request by following CORS policy.
Actually, the request is already sent to the resource server, and the server also responded. However, browser blocks the response by CORS policy and does NOT return the response back to Javascript code.
This cross-origin sharing standard can enable cross-site HTTP requests for:
- Invocations of the
XMLHttpRequest
orFetch APIs
. - Web Fonts (for cross-domain font usage in @font-face within CSS), so that servers can deploy TrueType fonts that can only be cross-site loaded and used by web sites that are permitted to do so.
- WebGL textures.
- Images/video frames drawn to a canvas using drawImage().
- CSS Shapes from images.
The Cross-Origin Resource Sharing standard works by adding new HTTP 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 than GET
, or POST
with certain MIME types), the specification mandates that browsers "preflight" the request, soliciting supported methods from the server with the HTTP OPTIONS
request method, and then, upon "approval" from the server, sending the actual request. Servers can also inform clients whether "credentials" (such as Cookies and HTTP Authentication) should be sent with requests.
CORS failures result in errors, but for security reasons, specifics about the error are 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.
Simple requests do NOT trigger CORS prelight.
- One of the allowed methods:
GET
HEAD
POST
- Headers can only be some which are automatically set by the user agent:
Connection
User-Agent
- Headers can also allowed to be “CORS-safelisted request-header”:
Accept
Accept-Language
Content-Language
Content-Type
(but note the additional requirements below)- The only allowed values for the Content-Type header are:
application/x-www-form-urlencoded
multipart/form-data
text/plain
- The only allowed values for the Content-Type header are:
Other than simple requests discussed above, other requests must first send an HTTP request using the OPTIONS
method to the resource server on the other origin to determine if the actual request is safe to send.
OPTIONS
is an HTTP/1.1 method that is used to determine further information from servers, and is a safe method, meaning that it can't be used to change the resource.
OPTIONS
method can include headers:
Access-Control-Request-Method
- which method
Access-Control-Request-Header
- what custom headers
By including the above headers, OPTIONS
request can notify the resource server will be sent when the actual request is sent.
And the resource server can determine whether to accept the actual request or not.
OPTIONS
method can include headers:
Access-Control-Request-Method
- which methods
Access-Control-Request-Header
- what custom headers
Access-Control-Max-Age
- How many seconds for the response to the preflight request can be cached for without sending another preflight request
Access-Control-Allow-Origin
- What origins
By including the above headers, OPTIONS
response can notify the client what are accepted.
Credentialed requests that are aware of HTTP cookies and HTTP Authentication information.
If the resource server does NOT respond with a header Access-Control-Allow-Credentials: true
, the browser will REJECT any response and the response would be ignored and NOT made available to web content.
Preflight requests must never include credentials.
The response to a preflight request must specify Access-Control-Allow-Credentials: true
to indicate that the actual request can be made with credentials.
When responding credentialed requests, the resource server must specify an origin instead of wildcard *
.
When making credentialed requests to a different domain, third-party cookie policies will still apply.
If the server specifies a single origin (that may dynamically change based on the requesting origin as part of a white-list), then the server should also include Origin in the Vary response header — to indicate to clients that server responses will differ based on the value of the Origin request header.
For example:
- You visited https://request-1.com and got some contents through CORS request from https://response.com
- The https://response.com server responded without including
VARY: Origin
header - After a while, you visit https://request-2.com, which also needs some contents from https://response.com
- Your browser will use the cached response, which was cached when you visited https://request-1.com
- The
Access-Control-Cross-Origin
header in cached response does NOT include https://request-2.com but https://request-1.com - End up failing to get contents from https://response.com on https://request-2.com
It lets a server whitelist headers that Javascript in browsers are allowed to access.
It indicates how long the results of a preflight request can be cached.
It indicates whether or not the response to the request can be exposed when the credentials flag is true. See the above discussion for preflight and actual request.
It specifies the method or methods allowed when accessing the resource.
It indicates which HTTP headers can be used when making the actual request.
It indicates the origin.
Note that in any access control request, the Origin header is always sent.
To let the server know what HTTP method will be used when the actual request is made.
To let the server know what HTTP headers will be used when the actual request is made.