How to solve CORS errors when making an API request from Freshworks apps?

Cross-Origin Resource Sharing (CORS) is a mechanism or protocol allowing browsers opened with one website to access resources on other websites. Generally, for security reasons, browsers forbid requests that come in from cross-domain sources for security reasons. This is called the same-origin policy. However, there could be cases where you want to overcome this and access cross-domain resources, and CORS makes this possible.

How is CORS relevant for Freshworks apps?

The domain name that hosts the Freshworks apps (for example, d3h0owdjgzys62.cloudfront.net) differs from the Freshworks products’ domain name (for example, acme.freshdesk.com, acme.freshservice.com). So, any API requests made from the Freshworks apps to Freshworks products need CORS behavior to happen. This also applies to requests sent to third-party APIs from Freshworks apps, which occurs in every integration use case.

Is there a way to avoid the need for CORS?

Yes, but why is the CORS required in the first place?

Freshworks products are maintained and hosted by Freshworks. The app developer provides the Freshworks app source code that renders within the Freshworks product.

Then, how is this app rendered within Freshworks products?

The answer is iframes. The iframe is an HTML element with its rendering context and helps to create a sandbox. The Freshworks apps are loaded with a CDN domain (d3h0owdjgzys62.cloudfront.net).

Making an API request from Freshworks apps is common for most business use cases. When making an API request, the browser will deny the request with an error since the domain of the API request destination is different from the app’s frame domain. The browser by default applies the same-origin policy to API requests for security measure. To prevent it for the Freshworks app as they are rendered with a different domain, the CORS behaviour has to be applied to access resources from other domains including your own API servers and any third-party API services.

To enable CORS behavior for your API requests, the domain of the Freshworks app source has to be added to the “Access-Control-Allow-Origin” response header to the API services. This domain allowlisting may only sometimes be possible as the app developer would only own some of the API services that the app connects with.

Now, come to a way to overcome this

Freshworks has Request Method feature that acts as a proxy service to avoid the issues and requirements for CORS.

With the Request Method, the API request from the Freshworks apps is sent to the destination API through the Freshworks platform. Since the API requests are not sent directly by the browser, the restriction of cross-domain resource access is not applicable and avoided.

How to make API requests with the Request Method

To use the request method,

  1. As part of the app configuration, configure request templates.
  2. In manifest.json, declare the template(s) that the app code uses.
  3. From the app logic, invoke the configured template(s), and make HTTP requests to third-party domains.

Configuring request templates

Request templates are snapshots of all the HTTP requests that an app is expected to make.

  1. From the app’s root directory, navigate to the config folder and create a requests.json file if it not already exists.
  2. In requests.json, use the following syntax to configure all request templates the app is expected to use as JSON objects.

Example schema definition

"schema": {
    "method": "GET",
    "host": "northstar.freshdesk.com",
    "path": "/api/v2/tickets",
    "headers": {
        "Authorization": "Bearer <%= iparam.apikey %>",
        "Content-Type": "application/json"
    }
}

Declare Templates

From templates configured in the config/requests.json, in manifest.json, declare the ones the app code uses for a specific product.

  1. From the app’s root directory, navigate to the manifest.json file.
  2. Under product., use the following syntax and create a requests attribute.

Example manifest.json file with the request declaration:

{
    "platform-version": "2.3",
    "product": {
        "freshdesk": {
            "location": {
                "ticket_sidebar": {
                    "url": "index.html",
                    "icon": "app_icon.svg"
                }
            },
            "events": {
                "onTicketCreate": {
                    "handler": "onTicketCreateHandler"
                }
            },
            "requests": {
                "createTicket": {},
                "getTickets": {}
            }
        }
    },
    "engines": {
        "node": "18.12.1",
        "fdk": "9.0.0"
    }
}

Here, the “createTicket” and “getTickets” are the templates declared to be used in the app.

Invoke the API request

The app code includes the invokeTemplate() method to send an HTTP request to a third-party domain. This method serves as a runtime API call. As part of the call, the app can pass a dynamic context and any other data the template requires.

In the front-end HTML files (such as iparams.html, index.html), include the client JS resource as follows:

<script src="{{{appclient}}}"></script>

Navigate to the app.js file and include the invokeTemplate() method using the following syntax.

client.request.invokeTemplate(requestTemplateName, {
  context: {},
  body: JSON.stringify(body)
});

Refer to the documentation for more information about the Request Method.