Various ways to validate API keys in the iparams page

What are the various ways to validate the Product API key in the iparams?

Be it any Freshworks product, to access the REST APIs, an API Key is required. It can be obtained either manually (Refer to API doc - Authentication section) or automatically (Refer to SDK doc - Installation parameters, data-bind feature), depending on the product.

Regardless, it needs to be validated before usage. There are a few ways to validate the product key depending on the scenario:

  • Standard iparams.json: Using domain & api_key iparam fields
  • Dynamic iparams.json: Using Callback validation & Request API
  • Custom Iparams.html: Using Request Method
  • Custom iparams.html, json: Using Server Method Invocation (SMI)

Standard iparams.json: Using domain & api_key iparam fields

This is a simple and recommended approach to obtain the api_key value. In the iparams.json, one can include a pair of domain and api_key for a particular product (should be marketplace-enabled) like so:

{
  "fd_domain": {
    "display_name": "Account",
    "description": "Please enter your Freshdesk sub-domain",
    "type": "domain",
    "required": true,
    "type_attributes": {
      "product": "freshdesk"
    }
  },
  "fd_api_key": {
    "display_name": "API Key",
    "description": "Please enter your API key",
    "type": "api_key",
    "required": true,
    "type_attributes": {
      "product": "freshdesk"
    },
    "secure": true
  }
}

Based on the value of type_attributes.product, not only is the styling taken care of, the validation is also done accordingly!

Dynamic iparams.json: Using callback validation

Iparams.json also can attach a callback function to a particular field. When the value changes, the associated callback function will be triggered. For instance, consider an iparams.json file like so

{
  "fd_domain": {
    "display_name": "Account",
    "description": "Please enter your Freshdesk sub-domain",
    "type": "text",
    "required": true
  },
  "fd_api_key": {
    "display_name": "API Key",
    "description": "Please enter your API key",
    "type": "text",
    "events": [{
      "change": "validateKey"
    }],
    "required": true,
    "secure": true
  }
}

Notice the presence of the events property in the second iparam. Basically, we register a change event handler to listen to field value changes. A corresponding callback with the name validateKey should be present in your app’s config/assets/iparams.js file. It might look like the following snippet.

/* global app,client, utils */
var timeout;
/**
 * App lifecycle method to initialize the app and to obtain the `client` object
 * More details on Dynamic Installation parameters can be found at the link below ⬇️
 * https://developers.freshdesk.com/v2/docs/installation-parameters/#dynamic_install_page
 */
app.initialized().then(
  function (_client) {
    window.client = _client;
  },
  function (error) {
    //If unsuccessful
    console.error(error);
  }
);

/**
 * Payload and other options can be specified using `options`
 * Notice the presence of the debounce logic to avoid rate-limiting issues
 * 
 * @param {string} value 
 */
function validateKey(value) {
  //Assume it is the validation/resource endpoint
  var url = "https://" + utils.get("fd_domain") + ".freshdesk.com/api/v2/settings/helpdesk";
  var options = {
    headers: {
      Authorization: btoa(value + ":X")
    }
  };
  var p = new Promise(function (resolve, reject) {
    // Do not hit the validation API immediately upon change
    // Wait for 500ms and if the user hasn't typed anything during that time, make a call
    clearTimeout(timeout);
    timeout = setTimeout(function () {
      client.request.get(url, options).then(
        function (data) {
          // Upon success, just resolve
          resolve();
        },
        function (error) {
          // Upon failure - send an appropriate validation error message
          reject("This key is invalid. Please enter the right one");
        }
      );
    }, 500);
  });
  return p;
}

As you can notice, the callback returns a promise which resolves based on the status of the Request API call. This method can be used in scenarios where you would like to use standard iparams.json with custom validation for a product that is not marketplace-enabled or a third-party product.

image

Custom Iparams.html: Using Request Method

On the Custom Installation Page, one can use Request Method to validate authentication credentials like API keys for Freshworks products and any third-party services. The methodology is similar to how it would be done in a web application. Here, the platform’s Request Method comes to the rescue of making API without needing a third-party library.

Let’s see an example code for the Request Method validation in the iparams.html.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <script
    src="https://static.freshdev.io/fdk/2.0/assets/fresh_client.js"></script>
  <link rel="stylesheet" href="./assets/iparams.css" />
</head>

<body>
  <main>
    <h3>
      Configuration page built using
      <code>iparams.html</code>
    </h3>

    <fw-input required="true" type="text" icon-left="items" label="domain"
      size="30" placeholder="subdomain.freshdesk.com" class="domain"></fw-input>

    <fw-input label="Freshdesk API Key" icon-right="magic-wand"
      placeholder="Freshdesk API Key" required="true"
      minlength="5" size="30" class="secure-field"></fw-input>

    <fw-button color="primary" id="btnVerify">Verify</fw-button>

  </main>

  <script src="./assets/iparams.js"></script>
  <script type="module"
    src="https://unpkg.com/@freshworks/crayons@v4/dist/crayons/crayons.esm.js"></script>
  <script nomodule
    src="https://unpkg.com/@freshworks/crayons@v4/dist/crayons/crayons.js"></script>
</body>

</html>

In the above-mentioned HTML file,

  • We have input fields for the Freshdesk domain and Freshdesk API key. For example, we are using Freshdesk credentials. But any third-party validations that use similar authentication schemes.
  • The Freshworks Crayons components are used for input fields and buttons. Thus, the same UI component library is imported via CDN URL.
const apiKey = document.querySelector('.secure-field');
const domain = document.querySelector('.domain');
const btnVerify = document.querySelector('#btnVerify');

function postConfigs() {
  return {
    __meta: {
      secure: ['apiKey']
    },
    api_key: apiKey.value,
    domain_url: domain.value
  };
}

function getConfigs(configs) {
  let { api_key, domain_url } = configs;
  apiKey.value = api_key;
  domain.value = domain_url;
  return;
}

let verified = false;
async function verify() {
  try {
    var response = await client.request.get(`https://${domain.value}/api/v2/tickets`,
      {
        headers: {
          Authorization: `Basic ${btoa(apiKey.value)}`,
          'Content-Type': 'application/json'
        }
      });
    var { status } = JSON.parse(response);
    if (status == 200) {
      verified = true;
    };
  } catch (error) {
    console.error('Error: Failed to validate the API key');
    console.error(error);
    if (status == 401) {
      console.error('Error: Domain or API key is invalid')
    };
  }
}

async function validate() {
  return verified;
}

document.onreadystatechange = function () {
  if (document.readyState === 'interactive') renderApp();
  async function renderApp() {
    try {
      let client = await app.initialized();
      window.client = client;

      btnVerify.addEventListener('fwClick', verify);
    } catch (error) {
      return console.error(error);
    }
  }
};

In the above-mentioned script file,

  • The validate, getConfigs, and postConfigs functions are mandatory by the platform and work in a certain way. Refer to the documentation for their detailed functionality and why they are mandatory on the custom installation page.
  • After the page is loaded, the button click event listener is added for the fwClick button component.
  • The verify function has the validation functionality by making an API with the given Freshdesk domain and API key to a GET API. If the API succeeds, the given inputs are valid and not otherwise.
  • The validate function will return true or false based on the API’s success or failure.

Note: The API is made in the browser, and all the details will be visible in the browser developer tools.

This shows how authentication credentials can be validated on the custom installation page.

Custom Iparams.html: Using Server Method Invocation (SMI)

Server Method Invocation (SMI) & Request Method calls are possible from the Installation pages. In the case of SMI, one can delegate the validation to an SMI method and pass the encoded parameters from the install pages. The validation status can be determined based on the values returned by the renderData callback.

This option can be chosen when the API request needs to happen in a secure environment. Refer to the Server Method Invocation (SMI) documentation for more information with examples.

6 Likes

3 posts were merged into an existing topic: Auto-Fill Sub-Domain & API Key on Install Page

is it necessary to ask user to to enter his freshdesk url?

is there any way we can fetch it dynamically in server.js (server method invocation)?

2 Likes