Step 5 - Create Your Own Search Endpoint With Authentication - API Key and Search Tokens

As of now, the only thing you were able to query was a demo endpoint indexing public sources.

In this step of the tutorial, you will create an endpoint on the Coveo Cloud infrastructure that you can use to securely index and query your own items.

This tutorial only covers the case where you can authenticate against a Coveo Cloud V2 infrastructure. It does not cover Coveo Cloud V1 or on-premises authentication.

If you are authenticating against a Coveo Cloud V1 infrastructure, the same basic principles apply, although you cannot create an API key yourself. You rather need to contact Coveo Support so they can create one for you. You will also need to use the cloudplatform.coveo.com URL to access your organization in this tutorial (rather than platform.cloud.coveo.com).

On-premises authentication is more complex, but the process is documented (see On-Premises).

If you significantly modified the ./bin/index.html page in previous steps of this tutorial, you can undo these changes by rebuilding the project. In order to do so, run the following command line from the top of the tutorial project folder:

npm run build

Create a New Coveo Cloud Organization

To create a new organization, you can use the Coveo Platform API. All available calls are documented in Swagger. You can access the REST API call to create an organization here: https://platform.cloud.coveo.com/docs?api=Platform#!/Organizations/rest_organizations_post.

Before making the call, you will need to log into the Coveo Platform by clicking on the exclamation mark.

You can then log in using one of the login providers, like Google or Salesforce.

The only required parameter for this call is the name you want to give to your organization.

Create New Sources

Once the REST API call to create an organization has been successful, access your organization from platform.cloud.coveo.com.

There are many options in the Coveo Administration Console of your newly created organization. To learn about them, see Coveo Cloud V2.

The rest of this tutorial will not go in-depth about the different parts of the Coveo Administration Console and will assume that you have created several new sources of your choice.

For this tutorial, you should index at least one source with public content (e.g., a website, a YouTube channel, etc.), and one source with secured content (e.g., Salesforce, Gmail, etc.).

Create an API Key with the Right to Execute Query

Create an API key with the only privilege being Execute queries (see Adding and Managing API Keys).

Create a New Search Endpoint

Create a new SearchEndpoint instance with the following configuration. Remember to replace [paste your API key here] with your actual API key.

document.addEventListener("DOMContentLoaded", () => {
  var root = document.body;
  Coveo.SearchEndpoint.endpoints["default"] = new Coveo.SearchEndpoint({
    restUri: "https://platform.cloud.coveo.com/rest/search",
    accessToken: "[paste your API key here]"
  });
  Coveo.init(root);
})
  • If your Coveo Cloud organization is in the HIPAA environment, set the restUri option to https://platformhipaa.cloud.coveo.com/rest/search when configuring your SearchEndpoint.
  • If your Coveo Cloud organization is deployed in multiple regions, set the restUri option to https://globalplatform.cloud.coveo.com/rest/search when configuring your SearchEndpoint (see Multi-Region Deployments).

You should now be able to query your newly created index.

While the platform is creating the index, the organization has no accessible endpoint. Therefore, until the index is built (which might take a few minutes), any search request you send will return a 408 Request Timeout error with a NoEndPointException warning message.

Q: Is it not extremely unsafe to paste an API key in the JavaScript code of a real search page?

A: To make it safe, you will have to control the privileges of the API key.

For instance, if the API key only has the privilege to Execute queries, then the only thing one can do with it is executing queries on publicly available content.

This can be explained by the fact that the identity bound to this API key is an email address with platform@coveo.com as its owner. This identity is considered anonymous.

For search pages publicly available on the Internet (with no secured content), creating a search endpoint with such a configuration is perfectly valid.

If that is all you actually need to do, you can skip the rest of this step of the tutorial and move on to Step 6 - Result Templates.

Accessing Secured Content

With an API key having only Execute queries as a privilege, it is impossible to access secured content. This API key possesses only one identity, which is “anonymous”.

In order to access secured content, you will need to create search tokens. You can obtain search tokens by using an API key with the privilege to impersonate users (i.e., the Allowed access level on the Impersonate domain) (see Privilege Management and Impersonate Domain).

An API key with the privilege to impersonate users can create search tokens which can impersonate any identity.

The following steps summarize a typical scenario:

  1. A user logs into a web server of some sort. This could be a Salesforce organization, a WordPress website, an IIS website, a Node.js website, etc.
  2. The user accesses the Coveo search page served from the website.
  3. The website into which the user initially logged has information about this user identity. It could be their email or username, for example. This information can be mapped to an identity in a secured source in the Coveo index.
  4. Backend code can securely store and access the API key with the privilege to impersonate users (i.e., the Allowed access level on the Impersonate domain).
  5. Backend code sends a POST request to the Coveo Platform (see Search Token Authentication).

The web server can now serve the search page. This means that the web server needs to serve the HTML content of the page and to be able to supply the search token to the JavaScript code that will configure the search endpoint in the search page. This can be done in different ways:

  • In a Salesforce organization, you could print the token using Apex code in the Visualforce page.
  • With an IIS website, this could be done with ASP.NET code.
  • In a Node.js website, this could be done with a templating engine, or by providing a backend call that the JavaScript code could access using an XMLHTTPRequest.

Thus, the JavaScript configuration remains the same, except you must use a search token instead of an API key, as shown in the following code excerpt:

document.addEventListener("DOMContentLoaded", () => {
  var root = document.body;
  Coveo.SearchEndpoint.endpoints["default"] = new Coveo.SearchEndpoint({
    restUri: "https://platform.cloud.coveo.com/rest/search",
    accessToken: "[this would be the generated search token]"
  });
  Coveo.init(root);
})

The search token effectively acts as a username and password against the Coveo Platform for the user who is logged in. Consequently, a user logged in on the website serving the search page does not need to log in on the Coveo Platform to access secured content.

Search tokens are JSON web tokens (see https://jwt.io/). They are unique for each user and JavaScript code cannot tamper with them. Search tokens also expire after a certain time (24 hours by default).

The API key with the privilege to impersonate users (i.e., the Allowed access level on the Impersonate domain) is very important (see Privilege Management and Impersonate Domain). It should never be used directly in an HTML page where anyone can see it. The responsibility to keep the API key secure and accessible only to people with adequate privileges falls onto the implementation.

What’s Next?

You should now proceed to Step 6 - Result Templates.