Cross-Origin Resource Sharing (CORS)
Cross-Origin Resource Sharing (CORS) is a facility that allows a client to interact with resources from an origin that is different from where the first resource was obtained.
- Simple versus preflight requests
- CORS request headers
- CORS response headers
- Requests with credentials
CORS is the process that allows a client to make HTTP requests from one server to another server. This is not normally allowed due to enforcement of the same-origin policy (SOP). The SOP is intended to prevent certain types of attacks, such as a malicious server running a script on a client’s browser that will allow them unauthorized access to local files.
An origin is the same if the host, port, and protocol are all the same. For example, if a server is using an HTTP Connection to serve a resource, then an HTTPS connection from the same server does not have the same origin. As such, the browser will not allow these types of HTTP requests unless they include the proper CORS headers.
Access to CORS functionality is accomplished using APIs such as XMLHttpRequest or Fetch, which both help to lower the risks associated with interacting with resources from multiple Origins. The CORS protocol essentially allows HTTP responses to include a direction stating that they are shareable with servers from different Origins.
Simple versus preflight requests
CORS requests are either simple or require an accompanying preflight request. A request preflight is a mechanism used to obtain permission in advance of sending the actual HTTP request.
If the CORS request is simple then a preflight request is not necessary. A simple HTTP request operates with several constraints that include, among other things, restrictions on the type of HTTP method, the HTTP headers it can include, and the type of content. For example, simple HTTP requests can only use the GET, HEAD, and POST methods.
For non-simple HTTP requests, the preflight will use special HTTP request headers to obtain permission and generally interact with the second server. Information about what is allowed will be returned using a special set of HTTP response headers.
CORS request headers
If an HTTP request includes the HTTP Origin header, it may be working inside of a CORS operation. A CORS preflight request verifies whether the protocol is supported. This is done by using the HTTP OPTIONS method that includes the HTTP request headers Access-Control-Request-Method and Access-Control-Request-Headers.
CORS response headers
A CORS-supporting server can respond to such HTTP requests by including several HTTP headers.
Access-Control-Allow-Origin specifies the origin from which the server will accept CORS requests. Only one domain can be specified; however, a wildcard is permitted. The wildcard is an asterisk (
*) allowing all domains, although this is a security risk and shall only be used for open or public systems. Values other than these will be rejected by the browser.
If the value for Access-Control-Allow-Credentials is set to true, it means that the HTTP request can include credentials such as HTTP Cookies. When the HTTP header is not present, the default value is false. HTTP Cookies are not typically included in CORS requests to prevent CSRF attacks.
Access-Control-Expose-Headers specifies which non-default HTTP headers will be exposed to the client. CORS responses that include non-default and non-specified HTTP headers will still be successful, although the client will not expose them. A common example of a non-default HTTP header is Date. The default HTTP headers in a CORS response are Cache-Control, Expires, Last-Modified, Content-Type, Content-Language, and Pragma.
The Access-Control-Max-Age cache-control option specifies the number of seconds that the preflight request will be cached for.
Some browsers have their own limit and specifying a higher one will not allow it to be exceeded.
Requests with credentials
For a HTTP request that includes credentials, there are additional restrictions on the server due to security concerns. Wildcard access using the asterisk (
*) is not allowed for Access-Control-Allow-Origin, Access-Control-Allow-Methods, or Access-Control-Allow-Headers.
In this example, the client requests a resource from the origin. The HTTP request is successful but not fully complete, as the client needs to interact with resources accessible at database.example.re. This qualifies as a different origin. A preflight request is then made to see if CORS is supported for the HTTP POST method, where the intention is to send a textual XML file.
This preflight request includes the Origin HTTP request header, which specifies the first origin. Notice that the Origin header includes
http://; this is mandatory because the protocol needs to match.
The new server responds to state that it will accept CORS requests from the specified origin for several HTTP methods, including POST. Subsequent HTTP requests to the new origin will continue to include the Origin HTTP request header.
Initial request – first server
GET /clientlist.html HTTP/1.1 Host: www.example.re
Response from origin server
HTTP/1.1 200 OK Content-Type: text/html Content-Length: 2500 <HTML document included in message body>
OPTIONS / HTTP/1.1 Host: database.example.re Origin: http://www.example.re Access-Control-Request-Method: POST Access-Control-Request-Header: Content-Type
Response to preflight request
HTTP/1.1 200 OK Access-Control-Allow-Origin: http://www.example.re Access-Control-Allow-Methods: POST, PUT, DELETE, OPTIONS Access-Control-Allow-Headers: Content-Type …
Subsequent request(s) for image(s) from new origin
POST /updateclient.xml HTTP/1.1 Host: database.example.re Origin: http://www.example.re Content-Type: text/xml <Data for POST included in message body>
Cross-Origin Resource Sharing (CORS) is used to provide access to resources available at domains that are different from that of the original resource. HTTP requests can be simple or use an accompanying preflight request, where a preflight request is used to obtain permission in advance of making the original HTTP request. Not all servers support CORS, and many only support a subset of HTTP methods and HTTP headers. There are security concerns that need to be considered, such as whether sending credentials is allowed, when implementing CORS.