Consider the following scenario: You attempt to use your website’s GET() endpoint to retrieve some data from an API, but an error results.
The Access-Control-Allow-Origin header has a value of “some url” that is not equal to the supplied origin,” or “The Access-Control-Allow-Origin header has a value of “No Access-Control-Allow-Origin header is present on the requested resource,” written in red text, indicating that your request was denied due to CORS policy.
What is CORS?
CORS (Cross-Origin Resource Sharing) is a method that permits resources to be loaded from one origin to another while preserving the security and integrity of the website. Popular web browsers like Chrome and Mozilla Firefox use this security technique to determine which cross-site requests are secure.
Modern browsers use the same-origin policy to limit access from scripts to resources outside their domain for security concerns. This policy was created in reaction to malicious activities including cross-site request forgery (CSRF) assaults and theft of personal information from other web servers.
Why does same origin exist?
This indicates that a cookie is stored for https://exampleapi.com when you log into https:// exampleapi.com. The bank may have developed a REST API at https:// exampleapi.com/api if it is a single-page React application so that the SPA can interface with it using AJAX.
- Using CORS headers, the resource origin sends a preflight request to the external web server.
- The preflight request is then validated by the external web server to ensure that scripts are authorized to make the request.
- The external web server replies with its own set of HTTP headers that specify the allowed request methods, origins, and custom headers after the request has been confirmed. Information on whether it is appropriate to pass along credentials, such as authentication headers, may also be included in this final server response.
Why do we need CORS?
- A different scheme (HTTP or HTTPS)
- An alternative domain or port
Cross-origin access, however, may be required or even desired in certain situations. As in the case of a React SPA that communicates with an API backend that is hosted on a different domain.
As you can see, CORS is an important protocol for making cross-domain requests possible, in cases where there’s legitimate need.
How does CORS work?
CORS requests come in two types: simple requests and preflighted requests. The criteria for determining if a request is preflighted are discussed later:
A CORS request that doesn’t need to go through any preflight requests (initial checks) is referred to as a simple request.
- AJAX request is started by a browser tab that is open to https://www.mydomain.com. GET widgets at https://api.mydomain.com
- The browser automatically inserts the Origin Request Header along with headers like Host for cross-origin requests
- The Origin request header is examined by the server. The Access-Control-Allow-Origin is set to the value in the request header Origin if the Origin value is allowed.
- The Access-Control-Allow-Origin header is checked by the browser to verify if it matches the origin of the tab when it receives the answer. If not, the reply is suppressed. If the Access-Control-Allow-Origin either contains the wildcard * operator or exactly matches the single origin, the check succeeds, as in this example.
The other kind of CORS request is a preflighted request. A preflighted request is a CORS request in which the browser must first make a preflight request (also known as a preliminary probe) to the server to determine whether the original CORS request can be processed. It is an additional HTTP request using the OPTIONS method. The browser performs this for every unsafe request that is intended to alter data — for example, POST, PUT, or DELETE requests.
We refer to the original CORS request as preflighted because it was preceded by a preflight request.
Common circumstances necessitating preflighted requests:
The Content-Type header for a website’s AJAX call to POST JSON data to a REST API is application/json.
- A website makes an AJAX call to an API and includes a token in the request header to authenticate the API. Authorization
- This means that a REST API frequently has the bulk of AJAX requests preflighted when it powers a single-page application.
Simple requests vs. pre-flighted requests:
Simple requests are defined as those that do not result in a CORS preflight. However, after the request has been determined to be a basic request, some requirements must be met. These circumstances are:
- The request’s HTTP method needs to be one of the following: head, Post, or Get
- Except for the headers that are automatically set by the user agent, the request headers should only contain CORS safe-listed headers like Accept, Accept-Language, Content-Language, and Content-Type.
- Only one of these three values, total, should be present in the Content-Type header: Multipart/form-data, application/x-www-form-urlencoded, or text/plain
- The XMLHttpRequest’s returned object has no registered event listeners.
- XMLHttpRequest must use the upload attribute.
- There shouldn’t be any ReadableStream objects in the request.
The request is regarded as a pre-flighted request if either of these requirements is not met. For these requests, the browser must first submit an OPTIONS method request to the alternative origin.
This is used to determine whether the actual request can be sent to the server without risk. The response headers to the pre-flighted request determine whether the real request is approved or denied. The request is not sent if the main request’s headers and these response headers conflict.
Suppose we faced the CORS error. There are many ways we could solve this issues depending on our access to the server on which the resources are hosted. There are two ways:
- Access to the backend server
- Access to only the frontend
Access to the backend:
You may set up the server to respond with the proper headers to enable resource sharing across various origins because CORS is essentially an HTTP header-based method. Look at the CORS headers we covered previously, and adjust the headers as necessary.
For example in node.js+express.js application:
The default configuration will be applied if a CORS configuration object is not given, which is identical to:
The following describes how to set up CORS on your server such that it will only accept GET requests from https://example.com with the headers Content-Type and Authorization and a preflight cache time of 10 minutes:
Access to the frontend:
If you don’t have access to the backend server like a public API. Die to this, you cannot add headers to the response received. So in that case you could use a proxy server that’ll add the CORS headers to the proxied request. The proxy server is available on https://cors-anywhere.herokuapp.com/. You can also build your own proxy server.
Instead of directly making the request to the server, simply append the proxy server’s url to the start of the API’s url.
Using the Access-Control-Allow-Origin * operator
CORS is a waiver of the same-origin rule that aims to maintain security. Most of CORS’ security rules are disabled while using *. In some situations, such as with an open API that is integrated into numerous websites run by third parties, wildcard is acceptable.
A separate domain for the API may increase security.
For instance, your main website’s API https://www.example.com/api may still respond with Access-Control-Allow-Origin: https://www. example.com while your open API https://api. example.com may respond with Access-Control-Allow-Origin: *.
Multiple domains are returned for the Access-Control-Allow-Origin header.
Unfortunately, the Access-Control-Allow-Origin: https:// example.com, https://www. example.com is not supported by the specification. The Origin request header can be used, but the server can only return one domain or *.
Choosing a wildcard, such as *.example.com:
Since wildcard can only be used to imply that all domains are allowed, this is not covered by the CORS specification.
Not including non-standard or protocol ports:
As the protocol is missing, Access-Control-Allow-Origin: example.com is invalid.
Similar to this, unless the server is genuinely running on a typical HTTP port like:80, you will see issues with Access-Control-Allow-Origin: http://localhost.
Ignoring the Origin header in the Vary response:
The majority of CORS frameworks perform this automatically; nonetheless, you must inform clients that server answers vary depending on the origin of the request.
Failure to define Access-Control-Expose-Headers:
The CORS request will still succeed if a needed header is missing, but any response headers that are not whitelisted will be hidden from view in the browser tab. For CORS requests, the following standard response headers are always exposed:
When Access-Control-Allow-Credentials is set to true, using wildcard:
A lot of people become caught up in this complicated issue. If response has Access-Control-Allow-Credentials: true, then the wildcard operator cannot be used on any of the response headers like Access-Control-Allow-Origin.
January 30, 2023 | Written by: Bilal Ul Haque