Cross Origin Resource Sharing (CORS)
What is CORS?
In order to explain what (CORS) is, it is necessary to cover additional security mechanisms like Same Origin Policy. SOP restricts how an application or script loading from one origin (defined as domain, port or protocol) can interact with other origins. This mechanism is applied with the goal of reducing possible exploits like accessing data from other domains, and loading other malicious scripts to relay data. CORS is a another security mechanism that is defined in the Fetch Living Standard that utilizes HTTP-headers to define origins for each HTTP request to a server. This allows for Cross Origin Resource Sharing and added flexibility on top of the Same Origin Policy.
How CORS handle requests
CORS support a secure way to handle cross-origin requests and data transfer between browsers and servers. AJAX using XMLHttpRequests and the JavaScript Fetch API both rely on CORS. With the use of HTTP headers clients and servers can pass information and describe what origins are allowed to read/write information from a browser. CORS requests can be simple requests with allowed methods like GET, POST, or side-effect causing requests that require “pre-flight” approval.
Simple Requests
A simple request is one that uses the allowed methods: GET, HEAD, POST, and is restricted to certain headers (content-language, accept-language, etc) - these kind of requests do not trigger a pre-flight authorization check. Simple requests must meet all the following conditions:
Allowed Methods: GET, HEAD, POST
Allowed Headers: Accept, Accept-Language, Content-Language, Content-Type*
Allowed Content-Types: application/x-www-form-urlencoded, multipart/form-data, text/plain
Preflight Requests
Other requests that do not meet the above requirements (utilizing additional headers, etc) require use of the HTTP OPTIONS method to send additional information prior to the actual request. This OPTIONS stage asks for the Access-Control-Request-Method (defines the HTTP method the request will be making), and the Access-Control-Request-Headers that will define the headers the request will be sending.
The response headers returned from a preflight request will determine if the request can be processed. The Access-Control-Allow-Origin header can help the server define whether all origins can be included (as represented by the * wildcard), a specific origin, or even set to null. It is currently recommended not to return null due to possible serialization which may allow for origins with a “null” header.
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>
Access-Control-Allow-Origin: null
Request Options in Fetch
The fetch API can accept a second parameter, an init object that controls everything from the HTTP methods, to header options, including cors policy.
async function postData(url = '', data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData('https://example.com/answer', { answer: 42 })
.then(data => {
console.log(data); // JSON data parsed by `data.json()` call
});