cs-icon.svg

Understanding and Resolving CORS Error

Cross-Origin Resource Sharing (CORS) is a browser mechanism that allows controlled access to resources located outside of a given domain

Generally, for security reasons, browsers forbid requests that come in from cross-domain sources. However, there could be cases where you want to overcome this and access cross-domain resources, and CORS makes this possible.

There is another concept known as Same-Origin Policy (SOP) which enables resource sharing on similar domains. In this guide, we will discuss the SOP and how it helps to secure websites. We will also discuss how CORS extends the flexibility and adds pace to the SOP.

Same-Origin Policy (SOP)

The Same-Origin Policy was developed as a security mechanism for browsers to protect resources from malicious attacks. SOP allows resource sharing (data exchange) between two objects with the same origins.

This means that the origin of two websites should be the same if they want to share resources. For two websites to have the same origins, the websites should have the same domain, port number, and protocol type. If any one of these three properties is found different, then the sources are considered different origins.

While SOP is considered a restrictive system, it is highly secured, eliminating potential attacks on websites through cross-domain resources. SOP offers security to websites but can also be a hurdle to interact with third-party websites. Many dynamic websites regularly share a cross-domain resource with trusted websites and subdomains.

With SOP in place, access to cross-origin websites is restricted, and controlled access to resources is possible using Cross-Origin Resource Sharing (CORS).

Cross-Origin Resource Sharing (CORS)

CORS was introduced to provide easy and quick access to subdomains and trusted third parties. CORS enables controlled resource sharing between cross-domain origins as discussed earlier.

The browser and cross-origin website you are trying to access collectively exchange HTTP headers that define trusted web origins and associated properties for access control, as defined by CORS specifications.

CORS offers controlled access to cross-domain websites and hence is well secured. CORS is widely implemented to tackle limitations introduced by SOP. However, if poorly executed, CORS can cause severe security risks. Improper configuration of CORS may present some challenges and errors.

Let us learn more about CORS errors and best practices to avoid them.

Understanding and Fixing CORS Error

CORS is implemented on the server-side; it cannot be reconfigured on the client-side. The CORS behavior, commonly termed as CORS error, is a mechanism to restrict users from accessing shared resources.

This is not an error but a security measure to secure users or the website which you are accessing from a potential security breach.

This breach may occur due to incomplete or improper HTTP headers on the client-side implementation (eg. missing authorization data such as API key).

Best Practices to Avoid CORS Errors

Let's discuss some of the best practices for avoiding CORS errors by using a Custom Field Extension in Contentstack.

Proxy the API Request while using External Calls in an Extension

CORS proxy can be a helpful solution to make cross-origin requests. The proxy layer sits between your request and its destination without knowing the request’s origin.

Thus, though the request comes from an unknown source, the CORS proxy makes it seem that it is a request from an allowed location.

To learn how to do this, here is the list of CORS-Proxy which you can use for your website.

Free proxies can be great for testing, but relying on a free third-party tool is not advisable for something you will use on the production site. In such cases, a more stable solution is to call the API from a server and make the data available on the client-side.

Use a Serverless Function

A more commonly used solution to resolve CORS error is to use a serverless function. It is an alternate way to proxy your requests, but instead of relying on a free third-party service, you can build your micro-infrastructure to call a web service and feed data to an API endpoint.

Popular serverless functions include AWS Lambda, Azure Functions, and Google Cloud functions. These services allow you to get just enough server space to run a function or two, as you do not need much space to run a function that calls a web service to return some data.

To understand this better, let's consider a use case:

A user wants to create an extension in Contentstack which will fetch the maps data from the Google Maps API to get data related to longitude and latitude within your entry.

The user has to follow the steps below:

  1. Create a custom extension in Contentstack using the UI extension SDK. This extension will make an API call to the Google Maps API to fetch the data in your entry.
    The request will fail due to the cross-origin policy set at Google’s server, which will not let you fetch the data, resulting in a CORS error at your client-side.
  2. To solve this problem, you can create an API Gateway URL in AWS with CORS enabled to serve the responses from the Google Maps API with our AWS Lambda function. For example:
     exports.handler = async (event) => {
    try{
    // some code...
        return {
          statusCode: 200,
          headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Headers':
              'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
            'Access-Control-Allow-Methods': 'OPTIONS,POST',
            'Access-Control-Allow-Credentials': true,
            'Access-Control-Allow-Origin': '*',
            'X-Requested-With': '*',
          },
          body: JSON stringified object,
        };
      } catch (error) {
        console.log(error);
        return {
          statusCode: 500,
          headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Headers':
              'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
            'Access-Control-Allow-Methods': 'OPTIONS,POST',
            'Access-Control-Allow-Credentials': true,
            'Access-Control-Allow-Origin': '*',
            'X-Requested-With': '*',
          },
          body: JSON.stringify({
            name: error.name,
            code: error.code,
            message: error.message,
          }),
        };
      }
    };
    
  3. The extension that we have created will make an appropriate call i.e., GET, POST, and so on, to our API Gateway URL & trigger our lambda function.
  4. The AWS Lambda will then return the maps API response to our client-side. This will fetch the maps data from Google Maps within your entry in Contentstack.

Note: For external hosting of the extension source code, the 'allow-same-origin' option will be enabled. Here, the origin refers to the domain where you've hosted the extensions. Also, ensure that the response header has the exact origin URL passed in the request header.
For Contentstack-hosted extensions, the iframe's origin will be null as we don't enable the 'allow-same-origin' flag.

CORS Issue in Frontend Frameworks

The CORS configuration can sometimes be tricky to achieve, and hence developers serve both the backend and frontend under the same domain in production.

To minimize this effort and provide flexibility to work with CORS, React, Nuxt, Express, etc. allow users to replicate the setup in development. This setup is done at the server end, so whenever a cross-origin request is made to the server, we can use a middleware like http-proxy-middleware to proxy requests.

Furthermore, we can also redirect and change the path of the request by using options like pathRewrite.

Was this article helpful?
^