Configuring Authenticated Search

If you followed the steps in Deploying Coveo for Microsoft Dynamics 365 in a Portal, you have a portal that’s powered by Coveo and able to deliver relevant content more accurately to your visitors. However, until now, all users were considered anonymous. In practice, it means that, through a Coveo-powered search interface, they can only access public source content.

Since the user is known, the content of sources that index permissions to which they’re associated becomes available to them, allowing Coveo Machine Learning to deliver even more personalized content, improving the user experience and the accuracy of Automatic Relevance Tuning (ART).

In this section, you’ll learn how to create a search token for a user that’s logged into your portal. For more details on how search token authentication works, see Search Token Authentication.

Running a Search Token Service

For security purposes, search tokens need to be generated on the server side (see Requesting a Search Token). That said, you need to run a server application that will be called from your portal.

Download and Run the Node.js Token Server Sample

The Coveo for Microsoft Dynamics 365 team created a straightforward, working example on GitHub that demonstrates how a search token can be created for a user, authenticated or not (see node-token-server).

This code sample (dependencies included) is a very simple demonstration, for reference only. It’s provided as-is, without warranty of any kind, express or implied (see License). Coveo encourages you to develop an implementation that properly fits all your business and security requirements.

  1. Download the GitHub repository master.zip and extract it.

  2. Open /samples/node-token-server/Index.ts, locate the config object and modify the value of its properties accordingly:

     // -----------------------------------------------------------------------------
     // Change this configuration accordingly to represent your environment.
     const config = {
         portalUrl: "<your_portal_url>", // Example: https://yourportalurl.microsoftcrmportals.com
         coveoApiKey: "<your_API_key>", // The API key used to query Coveo and create a search token. It must have at least the privilege "Impersonate" enabled.
         coveoPlatformUrl: "platform.cloud.coveo.com" // The Coveo Cloud URL.
     };
     // -----------------------------------------------------------------------------
    

    For information on the privileges required by this particular API key, see Impersonate Domain. For general information on API keys, see Create an API Key and Adding and Managing API Keys.

Run the Server Locally

  1. Install Node.js and NPM.

  2. Open a terminal window and navigate to /samples/node-token-server.

  3. Run npm start, which runs the server on the port displayed in your terminal.

    http://localhost:5950/

  4. Open a web browser and navigate to the sample application. You should see a message indicating that the token server is running.

To terminate the process of the web server, press Ctrl+C in your terminal window.

The Token Endpoint

The server exposes a POST endpoint /token that returns search tokens.

const server: http.Server =
    express()
        ...post("/token", getCoveoToken)...

For more details on the implementation, see Index.ts, DynamicsPortalAuthTokenDecoder.ts, and CoveoSearchTokenGenerator.ts.

Calling the Search Token Service From Your Portal

Once the search token service is up and running, your portal should be configured to fetch tokens from it.

Adding a Site Setting for the Search Token Service URL

In Microsoft Dynamics 365, create the following portal site settings (see Manage portal site settings):

  1. In the Name box, enter Coveo/TokenUrl.

  2. In the Website menu, select your portal.

  3. In the Value box, enter the URL of your search token service.

    http://localhost:5950/token

  4. In the Description box, enter URL of the search token service.

Creating a Coveo Search Token Fetched Event

In Microsoft Dynamics 365, create a new web template (see Store source content by using web templates):

  1. In the Name box, enter Coveo Search Token Fetched Event.

  2. In the Website menu, select your portal.

  3. In the Source box, enter the following code, which triggers a CoveoSearchTokenFetched event once the token is fetched from the server:

     <script type="text/javascript">
         {% assign coveoTokenUrl = settings['Coveo/TokenUrl'] | default:'' %}
         {% assign organizationId = settings['Coveo/OrganizationId'] | default:'' %}
         {% assign platformUrl = settings['Coveo/PlatformUrl'] | default:'' %}
         {% assign usageAnalyticsUrl = settings['Coveo/UsageAnalyticsUrl'] | default:'' %}
         const tokens = {
             getPortalToken: (callback) => {
                 const fetchAndCallback = () => {
                     var xhttp = new XMLHttpRequest();
                     xhttp.onreadystatechange = function() {
                         if(xhttp.readyState == XMLHttpRequest.DONE) {
                             callback(xhttp.responseText);
                         }
                     }
                     xhttp.open("GET", "/_services/auth/token");
                     xhttp.send(null);
                 }
                 {% if user %}
                     fetchAndCallback();
                 {% else %}
                     callback();
                 {% endif %}
             },
             getCoveoSearchToken: (portalToken, success) => {
                 var xhttp = new XMLHttpRequest();
                 xhttp.onreadystatechange = function() {
                     if(xhttp.readyState == XMLHttpRequest.DONE) {
                         var response = JSON.parse(xhttp.responseText);
                         success(response.coveoSearchToken);
                     }
                 }
                 xhttp.open("POST", "{{ coveoTokenUrl }}");
                 if (portalToken) {
                     xhttp.setRequestHeader("Authorization", portalToken);
                 }
                 xhttp.send(null);
             },
             dispatchFetchTokenEvent: () => {
                 // Dispatch only after DOM is loaded.
                 if (tokens.coveoSearchToken && tokens.isDomLoaded) {
                     const e = new CustomEvent('CoveoSearchTokenFetched', {
                     detail: {
                         token: tokens.coveoSearchToken,
                         organizationId: "{{ organizationId }}",
                         searchUrl: "{{ platformUrl }}rest/search",
                         usageAnalyticsUrl: "{{ usageAnalyticsUrl }}"
                         }
                     });
                     tokens.coveoSearchToken = "";
                     document.dispatchEvent(e);
                 }
             },
             coveoSearchToken: "",
             isDomLoaded: false
         };
         tokens.getPortalToken((portalToken) => {
             tokens.getCoveoSearchToken(portalToken, (coveoSearchToken) => {
                 tokens.coveoSearchToken = coveoSearchToken;
                 tokens.dispatchFetchTokenEvent();
             });
         });
         document.addEventListener('DOMContentLoaded', function () {
             tokens.isDomLoaded = true;
             tokens.dispatchFetchTokenEvent();
         });
     </script>
    

    Internet Explorer 11 doesn’t support the arrow function in the script above. If you need a workaround, see this Stack Overflow post.

  4. In the action bar, click Save and close.

Adding the Web Template to Coveo Resources

Open the web template Coveo Resources (see Adding a Web Template for Coveo Scripts and Stylesheets):

  1. In the Source box, after the last line, enter the following code:

     {% include 'Coveo Search Token Fetched Event' %}
    
  2. At the bottom of the page, click the floppy disk icon to save your modifications.

Using the Search Token to Initialize Coveo

The procedure that follows must be applied to all web templates that calls Coveo.SearchEndpoint.configureCloudV2Endpoint.

If you followed the steps in Deploying Coveo for Microsoft Dynamics 365 in a Portal and configured Case Deflection, the following web templates should be impacted by this procedure:

  1. Open the web template.

  2. In the Source box, modify the call to Coveo.SearchEndpoint.configureCloudV2Endpoint as instructed below:

    Before:

     <script>
         {% assign apikey = settings['Coveo/ApiKey'] | default:'' %}
         {% assign organizationId = settings['Coveo/OrganizationId'] | default:'' %}
         {% assign platformUri = settings['Coveo/PlatformUrl'] | default:'' %}
         document.addEventListener('DOMContentLoaded', function() {
             Coveo.SearchEndpoint.configureCloudV2Endpoint('{{organizationId}}', '{{apikey}}', '{{platformUri}}rest/search');
             ...
    

    After:

     <script>
         document.addEventListener('CoveoSearchTokenFetched', (e) => {
             Coveo.SearchEndpoint.configureCloudV2Endpoint(e.detail.organizationId, e.detail.token, e.detail.searchUrl);
             ...
    

    Internet Explorer 11 doesn’t support the arrow function in the script above. If you need a workaround, see this Stack Overflow post.

  3. At the bottom of the page, click the floppy disk icon to save your modifications.

  4. Repeat the steps above for every other template that meets the criteria.

Using the Search Token to Call Coveo Usage Analytics (Coveo UA)

The procedure that follows must be applied to all web templates that calls coveoua.

If you followed the steps in Deploying Coveo for Microsoft Dynamics 365 in a Portal, the following web template should be impacted by this procedure:

  1. Open the web template.

  2. In the Source box, modify the code as instructed below:

    Before:

     <script>
         document.addEventListener('DOMContentLoaded', function() {
             const apiKey = "{{ settings['Coveo/ApiKey'] | default:'' }}";
             const usageAnalyticsUrl = "{{ settings['Coveo/UsageAnalyticsUrl'] | default:'' }}";
             ...
    

    After:

     <script>
         document.addEventListener('CoveoSearchTokenFetched', function(e) {
             const apiKey = e.detail.token;
             const usageAnalyticsUrl = e.detail.usageAnalyticsUrl;
             ...
    

    At the end of the web template, your call to coveoua("init", apiKey, usageAnalyticsUrl) should send the new set of arguments.

At the end of this procedure, you should delete the site setting Coveo/ApiKey since it should no longer be referenced on the client side (see Add Coveo Site Settings.

Recommended Articles