--- title: Choose and implement a search authentication method slug: '1369' canonical_url: https://docs.coveo.com/en/1369/ collection: build-a-search-ui source_format: adoc --- # Choose and implement a search authentication method Any [search interface](https://docs.coveo.com/en/2741/) that relies on the [Coveo Platform](https://docs.coveo.com/en/186/) must perform [authenticated](https://docs.coveo.com/en/2120/) HTTP requests against the Search API and Usage Analytics Write API. The most commonly used methods are API key and [search token](https://docs.coveo.com/en/1346/) [authentication](https://docs.coveo.com/en/2120/). Each [authentication](https://docs.coveo.com/en/2120/) method offers its own set of benefits and drawbacks. This article provides an overview of each method along with diagrams illustrating some typical [authentication](https://docs.coveo.com/en/2120/) scenarios to help you choose and implement the method that best fits your needs. [%header,cols="3"] |=== |Method |Benefits |Drawbacks |[Public API Key](#public-api-key-authentication-scenario) a|* Simple implementation a|* Public API key can be used outside of intended client * External use of API key can result in misleading [Coveo Analytics data](https://docs.coveo.com/en/259/) * All [users](https://docs.coveo.com/en/250/) are considered [anonymous](https://docs.coveo.com/en/m5ki3986/) |[Private API Key](#private-api-key-authentication-scenario) a|* Private API key can't be used outside of intended client a|* Complex implementation * All [users](https://docs.coveo.com/en/250/) are considered [anonymous](https://docs.coveo.com/en/m5ki3986/) |[Search Token](#search-token-authentication) a|* You can enforce a [search hub](https://docs.coveo.com/en/1342/), [query pipelines](https://docs.coveo.com/en/180/), and/or [query](https://docs.coveo.com/en/231/) [filters](https://docs.coveo.com/en/2736/) through the [search token](https://docs.coveo.com/en/1346/) * [search tokens](https://docs.coveo.com/en/1346/) are temporary * [authenticated](https://docs.coveo.com/en/2120/) [users](https://docs.coveo.com/en/250/) can access secured content that they're allowed to see a|* Complex implementation |=== ## Authentication scheme The Search API and Usage Analytics Write API both rely on the _bearer_ [HTTP authentication scheme](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). All HTTP requests made to these services must include an `Authorization` header with a valid access token (for example, API key or search token): ```text Authorization: Bearer ``` > **Note** > > The preceding information is only useful if your [search interface](https://docs.coveo.com/en/2741/) **doesn't** rely on the [Coveo JavaScript Search Framework](https://docs.coveo.com/en/187/), which handles all HTTP requests to the Search API and Usage Analytics Write API on its own, assuming that: > > * A [search endpoint is configured](https://docs.coveo.com/en/331#configuring-a-new-search-endpoint). > > * An [`Analytics`](https://coveo.github.io/search-ui/components/analytics.html) component is present in the [search interface](https://docs.coveo.com/en/2741/). ## API key authentication An _API key_ is a non-expiring access token which carries a certain set of [privileges](https://docs.coveo.com/en/228/) in a [Coveo organization](https://docs.coveo.com/en/185/). To implement API key [authentication](https://docs.coveo.com/en/2120/), [create an API key](https://docs.coveo.com/en/1718#create-an-api-key) with the **Search - Execute queries** and **Analytics - Analytics data - Push** [privileges](https://docs.coveo.com/en/228/) in the target [Coveo organization](https://docs.coveo.com/en/185/), and ensure that this API key [authenticates](https://docs.coveo.com/en/2120/) all Search API and Usage Analytics Write API requests that originate from a specific [search interface](https://docs.coveo.com/en/2741/). All [queries](https://docs.coveo.com/en/231/) that are [authenticated](https://docs.coveo.com/en/2120/) with this API key will be performed as an [anonymous](https://docs.coveo.com/en/m5ki3986/) [user](https://docs.coveo.com/en/250/), so you should only use this method when working with public [sources](https://docs.coveo.com/en/246/) or [items](https://docs.coveo.com/en/210/) that don't have varying levels of security. API key [authentication](https://docs.coveo.com/en/2120/) can be implemented in two ways: * By [exposing a public API key in the client](#public-api-key-authentication-scenario). * By [storing a private API key on the server](#private-api-key-authentication-scenario). ### Public API key authentication scenario The fastest and simplest way to implement API key [authentication](https://docs.coveo.com/en/2120/) is to expose a public API key with **Search - Execute queries** and **Analytics - Analytics data - Edit** [privileges](https://docs.coveo.com/en/228/) directly in the client. However, there's no way to ensure that all of the Search API and Usage Analytics Write API requests that are [authenticated](https://docs.coveo.com/en/2120/) with this key originate from its intended [search interface](https://docs.coveo.com/en/2741/). This can result in the logging of invalid or incorrect [Coveo Analytics data](https://docs.coveo.com/en/259/), among other issues. ![Typical Public API Key Authentication Scenario](https://docs.coveo.com/en/assets/images/api-key.svg) In a typical public API key [authentication](https://docs.coveo.com/en/2120/) scenario: . The client requests the [search interface](https://docs.coveo.com/en/2741/) from the server. . The server generates the [search interface](https://docs.coveo.com/en/2741/) code, configures it with a public API key that has the **Search - Execute queries** and **Analytics - Analytics data - Edit** [privileges](https://docs.coveo.com/en/228/), and delivers it to the client. . When a [query](https://docs.coveo.com/en/231/) is triggered, the client calls the Search API through the [search interface](https://docs.coveo.com/en/2741/) to execute the [query](https://docs.coveo.com/en/231/), using its public API key to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. . The Search API executes the [query](https://docs.coveo.com/en/231/) against the [index](https://docs.coveo.com/en/204/) and returns only public [items](https://docs.coveo.com/en/210/) to the client. . The client calls the Usage Analytics Write API through the [search interface](https://docs.coveo.com/en/2741/) to log a search [event](https://docs.coveo.com/en/260/), using its public API key to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. . The Usage Analytics Write API logs a search [event](https://docs.coveo.com/en/260/) for an [anonymous](https://docs.coveo.com/en/m5ki3986/) [user](https://docs.coveo.com/en/250/). ### Private API key authentication scenario > **Note** > > This is more complicated to implement than [search token authentication](#search-token-authentication), and it provides fewer benefits. > Use [search token](https://docs.coveo.com/en/1346/) [authentication](https://docs.coveo.com/en/2120/) instead. A more complex but more robust way to implement API key [authentication](https://docs.coveo.com/en/2120/) is to store an API key with the **Search - Execute queries** and **Analytics - Analytics data - Edit** [privileges](https://docs.coveo.com/en/228/) on the server, so that the [search interface](https://docs.coveo.com/en/2741/) makes its requests against the server, which in turn makes requests to the appropriate [Coveo Platform](https://docs.coveo.com/en/186/) services. With this implementation, the user can't see the API key, so it can never be used outside of its intended [search interface](https://docs.coveo.com/en/2741/). Furthermore, you can implement your own throttling mechanism, which lets you better manage network traffic and avoid potential threats and issues. > **Note** > > You can't implement private API key [authentication](https://docs.coveo.com/en/2120/) in a [search interface](https://docs.coveo.com/en/2741/) that relies on the [Coveo JavaScript Search Framework](https://docs.coveo.com/en/187/). ![Typical Private API Key Authentication Scenario](https://docs.coveo.com/en/assets/images/private-api-key.svg) In a typical private API key [authentication](https://docs.coveo.com/en/2120/) scenario: . The client requests the [search interface](https://docs.coveo.com/en/2741/) from the server. . The server generates the [search interface](https://docs.coveo.com/en/2741/) code and delivers the code to the client. The returned [search interface](https://docs.coveo.com/en/2741/) _isn't_ configured with an API key. . When a [query](https://docs.coveo.com/en/231/) is triggered, the client forwards the [query](https://docs.coveo.com/en/231/) parameters to the server. . The server, acting as a proxy, calls the Search API to execute the [query](https://docs.coveo.com/en/231/) against the [index](https://docs.coveo.com/en/204/). The server uses a stored, private API key that has the **Search - Execute queries** and **Analytics - Analytics data - Edit** [privileges](https://docs.coveo.com/en/228/) to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. . The Search API executes the [query](https://docs.coveo.com/en/231/) against the [index](https://docs.coveo.com/en/204/) and returns only public [items](https://docs.coveo.com/en/210/) to the server, which then returns them to the client. . The server, acting as a proxy, calls the Usage Analytics Write API to log a search [event](https://docs.coveo.com/en/260/). The server uses the same private API key used in step 4 to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. . The Usage Analytics Write API logs a search [event](https://docs.coveo.com/en/260/) for an [anonymous](https://docs.coveo.com/en/m5ki3986/) [user](https://docs.coveo.com/en/250/). ## Search token authentication A [search token](https://docs.coveo.com/en/1346/) is a temporary, Search API-generated JSON web token which can be used to [authenticate](https://docs.coveo.com/en/2120/) certain Search API and Usage Analytics Write API requests as a specific [user](https://docs.coveo.com/en/250/). [search tokens](https://docs.coveo.com/en/1346/) can contain information about [users](https://docs.coveo.com/en/250/), such as their display names and user [groups](https://docs.coveo.com/en/202/), which may be used in [query pipeline conditions](https://docs.coveo.com/en/2793/). They can also be used to enforce specific [search hubs](https://docs.coveo.com/en/1342/), {query pipelines}, or [filters](https://docs.coveo.com/en/2736/) on the [queries](https://docs.coveo.com/en/231/) they [authenticate](https://docs.coveo.com/en/2120/). When a [search token](https://docs.coveo.com/en/1346/) is used to [authenticate](https://docs.coveo.com/en/2120/) a [query](https://docs.coveo.com/en/231/), the [index](https://docs.coveo.com/en/204/) only returns [items](https://docs.coveo.com/en/210/) that the [user](https://docs.coveo.com/en/250/) for whom the token was generated is allowed to see. You should use this method when working with [secured sources](https://docs.coveo.com/en/2093/) or [items](https://docs.coveo.com/en/210/) that have varying levels of security. [search tokens](https://docs.coveo.com/en/1346/) can be generated for [anonymous](https://docs.coveo.com/en/m5ki3986/) or non-[anonymous](https://docs.coveo.com/en/m5ki3986/) (that is, [authenticated](https://docs.coveo.com/en/2120/)) [users](https://docs.coveo.com/en/250/). ![Typical anonymous search token authentication scenario](https://docs.coveo.com/en/assets/images/anonymous-search-token.svg) In a typical [anonymous](https://docs.coveo.com/en/m5ki3986/) [search token](https://docs.coveo.com/en/1346/) [authentication](https://docs.coveo.com/en/2120/) scenario: . The client requests the [search interface](https://docs.coveo.com/en/2741/) for an [anonymous](https://docs.coveo.com/en/m5ki3986/) [user](https://docs.coveo.com/en/250/) from the server. . The server calls the Search API to request a [search token](https://docs.coveo.com/en/1346/) for an [anonymous](https://docs.coveo.com/en/m5ki3986/) [user](https://docs.coveo.com/en/250/). The server uses a stored, private [authenticated search API key](https://docs.coveo.com/en/1718#create-an-api-key) to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. . The Search API returns a [search token](https://docs.coveo.com/en/1346/) for an [anonymous](https://docs.coveo.com/en/m5ki3986/) [user](https://docs.coveo.com/en/250/) to the server. . The server delivers a [search interface](https://docs.coveo.com/en/2741/) which is configured with the [search token](https://docs.coveo.com/en/1346/) returned in step 3. . When a [query](https://docs.coveo.com/en/231/) is triggered, the client calls the Search API through the [search interface](https://docs.coveo.com/en/2741/) to execute the [query](https://docs.coveo.com/en/231/) against the [index](https://docs.coveo.com/en/204/). The client uses the [search token](https://docs.coveo.com/en/1346/) returned in step 3 to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. . The Search API executes the [query](https://docs.coveo.com/en/231/) against the [index](https://docs.coveo.com/en/204/) and returns to the client only the [query](https://docs.coveo.com/en/231/) result [items](https://docs.coveo.com/en/210/) that [anonymous](https://docs.coveo.com/en/m5ki3986/) [users](https://docs.coveo.com/en/250/) are allowed to see (that is, public [items](https://docs.coveo.com/en/210/)). . The client calls the Usage Analytics Write API through the [search interface](https://docs.coveo.com/en/2741/) to log a search [event](https://docs.coveo.com/en/260/). The client uses the [search token](https://docs.coveo.com/en/1346/) returned in step 3 to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. . The Usage Analytics Write API logs a search [event](https://docs.coveo.com/en/260/) for an [anonymous](https://docs.coveo.com/en/m5ki3986/) [user](https://docs.coveo.com/en/250/). ![Typical non-anonymous search token authentication scenario](https://docs.coveo.com/en/assets/images/non-anonymous-search-token.svg) In a typical non-[anonymous](https://docs.coveo.com/en/m5ki3986/) [search token](https://docs.coveo.com/en/1346/) [authentication](https://docs.coveo.com/en/2120/) scenario: . The client requests the [search interface](https://docs.coveo.com/en/2741/) for an [authenticated](https://docs.coveo.com/en/2120/) [user](https://docs.coveo.com/en/250/) from the server. . The server validates the [user](https://docs.coveo.com/en/250/)’s credentials and then calls the Search API to request a [search token](https://docs.coveo.com/en/1346/) for that [authenticated](https://docs.coveo.com/en/2120/) [user](https://docs.coveo.com/en/250/). The server uses a stored, private [authenticated search API key](https://docs.coveo.com/en/1718#create-an-api-key) to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. . The Search API returns a [search token](https://docs.coveo.com/en/1346/) containing information regarding the [authenticated](https://docs.coveo.com/en/2120/) [user](https://docs.coveo.com/en/250/) to the server. . The server delivers a [search interface](https://docs.coveo.com/en/2741/) which is configured with the [search token](https://docs.coveo.com/en/1346/) returned in step 3. . When a [query](https://docs.coveo.com/en/231/) is triggered, the client calls the Search API through the [search interface](https://docs.coveo.com/en/2741/) to execute the [query](https://docs.coveo.com/en/231/) against the [index](https://docs.coveo.com/en/204/). The client uses the [search token](https://docs.coveo.com/en/1346/) returned in step 3 to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. . The Search API executes the [query](https://docs.coveo.com/en/231/) against the [index](https://docs.coveo.com/en/204/) and returns to the client only the [query](https://docs.coveo.com/en/231/) result [items](https://docs.coveo.com/en/210/) that the [authenticated](https://docs.coveo.com/en/2120/) [user](https://docs.coveo.com/en/250/) is allowed to see. . The client calls the Usage Analytics Write API through the [search interface](https://docs.coveo.com/en/2741/) to log a search [event](https://docs.coveo.com/en/260/). The client uses the [search token](https://docs.coveo.com/en/1346/) returned in step 3 to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. . The Usage Analytics Write API logs a search [event](https://docs.coveo.com/en/260/) for the [authenticated](https://docs.coveo.com/en/2120/) [user](https://docs.coveo.com/en/250/). > **Note** > > In both [search token](https://docs.coveo.com/en/1346/) [authentication](https://docs.coveo.com/en/2120/) scenarios, you should implement a mechanism to ensure that the user can get a new [search token](https://docs.coveo.com/en/1346/) when their current one expires. ### Request a search token Make a POST request to `+https://.org.coveo.com/rest/search/token+`, where `` is the unique identifier of your [Coveo organization](https://docs.coveo.com/en/185/), to request a [search token](https://docs.coveo.com/en/1346/). Use an [authenticated search API key](https://docs.coveo.com/en/1718#create-an-api-key) to [authenticate](https://docs.coveo.com/en/2120/) the HTTP request. > **Important** > > This API key should never be exposed in client-side code because this could allow [users](https://docs.coveo.com/en/250/) to [impersonate](https://docs.coveo.com/en/2737/) other [users](https://docs.coveo.com/en/250/) and see search results that would otherwise be restricted. ### Search token authentication example A [search token](https://docs.coveo.com/en/1346/) creation call in which you only specify the required values: ```http POST https://myorganizationid9sd8df7s.org.coveo.com/rest/search/token HTTP/1.1 ​ Content-Type: application/json Authorization: Bearer **********-****-****-****-************ ``` **Payload** ```json { "userIds": [ { "name": "john_doe@some-domain.com", "provider": "Email Security Provider" } ] } ``` A successful request produces a JSON response containing the [search token](https://docs.coveo.com/en/1346/): ```json { "token": "fzKjcHdjPJKJVaJ2OjK0fzK2CI6dHJ1ZSwiZXhwIjoxNDY4Njk2NzEwLCJpYXQiOjE0lQGN..." } ``` > **Leading practice** > > Use the following identity to generate [search tokens](https://docs.coveo.com/en/1346/) for non-[authenticated](https://docs.coveo.com/en/2120/) [users](https://docs.coveo.com/en/250/): > > ```json { "name": "anonymous", "provider": "Email Security Provider", } ``` ### Request body properties The body of a POST request to `+https://.org.coveo.com/rest/search/token+` has the following properties: #### `userIds` (array of `RestUserId`, _required_) The [security identities](https://docs.coveo.com/en/240/) to associate with this [search token](https://docs.coveo.com/en/1346/). The `RestUserId` model has the following properties: ##### `name` (string, _required_) The name of the [security identity](https://docs.coveo.com/en/240/) (for example, `+"john_doe@some-domain.com"+`). ##### `provider` (string, _required_) The [security identity provider](https://docs.coveo.com/en/242/) of the [security identity](https://docs.coveo.com/en/240/) (for example, `"Email Security Provider"`). ##### `type` (string) The [security identity](https://docs.coveo.com/en/240/) type (for example, `"User"`). **Example** **The body of a search token creation call in which you specify the type of a `userIds` entry.** ```json { "userIds" : [ { "name" : "john_doe@some-domain.com", "provider" : "Email Security Provider", "type" : "User" } ] } ``` #### `filter` (string) The [query](https://docs.coveo.com/en/231/) expression filter to add to all [queries](https://docs.coveo.com/en/231/) [authenticated](https://docs.coveo.com/en/2120/) with this [search token](https://docs.coveo.com/en/1346/) (see [Query syntax](https://docs.coveo.com/en/1552/)). You can set this property to ensure that any [query](https://docs.coveo.com/en/231/) [authenticated](https://docs.coveo.com/en/2120/) with this token can only return results from a specific subset of [items](https://docs.coveo.com/en/210/) in the [index](https://docs.coveo.com/en/204/). **Example** **The body of a search token creation call in which you specify a constant query expression.** ```json { "filter" : "@objecttype=Case", "userIds" : [ { "name" : "john_doe@some-domain.com", "provider" : "Email Security Provider" } ] } ``` #### `pipeline` (string) The [query pipeline](https://docs.coveo.com/en/180/) to enforce when [authenticating](https://docs.coveo.com/en/2120/) a [query](https://docs.coveo.com/en/231/) with this [search token](https://docs.coveo.com/en/1346/). The [query pipeline](https://docs.coveo.com/en/1791/) that you specify for this property takes precedence over the possible output of all other [query pipeline routing mechanisms](https://docs.coveo.com/en/1666/) when [authenticating](https://docs.coveo.com/en/2120/) a [query](https://docs.coveo.com/en/231/) using this [search token](https://docs.coveo.com/en/1346/). **Example** **The body of a search token creation call in which you specify an enforced `pipeline`.** ```json { "pipeline" : "Tech Support Query Pipeline", "userIds" : [ { "name" : "john_doe@some-domain.com", "provider" : "Email Security Provider" } ] } ``` #### `searchHub` (string) The [search hub](https://docs.coveo.com/en/1342/) to enforce with this [search token](https://docs.coveo.com/en/1346/). The [search hub](https://docs.coveo.com/en/365#set-the-search-hub) is an important parameter for [Coveo Analytics](https://docs.coveo.com/en/182/), the [Coveo Machine Learning (Coveo ML)](https://docs.coveo.com/en/188/) service, and [query pipelines](https://docs.coveo.com/en/180/). **Example** **The body of a search token creation call in which you specify an enforced `searchHub`.** ```json { "searchHub" : "CommunitySearch", "userIds" : [ { "name" : "john_doe@some-domain.com", "provider" : "Email Security Provider" } ] } ``` #### `userGroups` (array of strings) The `userGroups` to pass when [authenticating](https://docs.coveo.com/en/2120/) an operation to log a search [event](https://docs.coveo.com/en/260/) with this [search token](https://docs.coveo.com/en/1346/). {User} [groups](https://docs.coveo.com/en/202/) can also be used in [query pipeline statements](https://docs.coveo.com/en/236/), such as `when $groups contains \"Employees\"`. **Example** **The body of a search token creation call in which you specify `userGroups` entries.** ```json { "userGroups" : [ "Tech Support", "Employee" ], "userIds" : [ { "name" : "john_doe@some-domain.com", "provider" : "Email Security Provider" } ] } ``` #### `userDisplayName` (string) The display name of the [user](https://docs.coveo.com/en/250/) with whom you want to associate this [search token](https://docs.coveo.com/en/1346/). **Example** **The body of a search token creation call in which you specify the end-user display name.** ```json { "userDisplayName" : "John Doe", "userIds" : [ { "name" : "john_doe@some-domain.com", "provider" : "Email Security Provider" } ] } ``` #### `validFor` (integer) The number of milliseconds for which the [search token](https://docs.coveo.com/en/1346/) will remain valid once it has been created. The minimum value is `900000` (that is, 15 minutes). The maximum and default value is `86400000` (that is, 24 hours). **Example** **The body of a search token creation call in which you specify the expiration time.** ```json { "validFor" : 1800000, "userIds" : [ { "name" : "john_doe@some-domain.com", "provider" : "Email Security Provider", } ] } ``` > **Note** > > The `RestTokenParams` model also exposes the `salesforceCommunityUrl`, `salesforceFallbackToAdmin`, and `salesforceUser` attributes, while the `RestUserId` model exposes the `authCookie` and `infos` attributes. > > Normally, you shouldn't manually specify values for these attributes. > They're intended for internal use by the [Coveo Platform](https://docs.coveo.com/en/186/).