How to authenticate Microsoft Dynamics 365 on behalf of user in Dialogue Studio

Introduction

Accessing Dynamics 365 OData requires an access token. This guide will tell you how to achieve this. In this example we will be looking up a contact.

 

Get an access and refresh token

First step is generating access and refresh token. We start with a function node.

Steps:

  1. Drag and drop a Function node.

  2. Open Function node.

  3. Enter the following function:

    Note Replace the following:

    msg.headers = {

    "Accept": "application/json",

    "Content-type": "application/x-www-form-urlencoded"

    };

    msg.credentials =

    {

    "client_id":"2ad88395-b77d-4561-9441-d0e40824f9bc&",

    "username":"[UserName]",

    "password":"[Password]",

    "resource":"[Resource]"

    }

    msg.payload = "client_id=" + msg.credentials.client_id + "&username=" + msg.credentials.username + "&password=" + msg.credentials.password + "&resource=" +msg.credentials.resource + "&grant_type=password"

    return msg;

 

Now that we prepared our message we can send the request. This is done using a HTTP Request node.

Steps:

  1. Drag and drop a http request node.

  2. Open Node:

    1. Method = Post

    2. URL = https://login.microsoftonline.com/common/oauth2/token

    3. Return = a parsed JSON object

  3. Connect the end of the Function node to the begin of the HTTP request node.

 

Next we want to check if our output was successful. This can be done with a Switch node.

Steps:

  1. Drag and drop a Switch Node.

  2. Open Node:

    1. Change Property to msg.statusCode.

    2. Add an option for a OK response.

      == 200

    3. Add the option otherwise for any other response.

  3. Connect end of the HTTP request node to begin of the Switch Node.

 

If the response was 200 OK then we can store the tokens. Note that an access token is only valid for one hour, for that reason we also store the expiration time. This can be done with a Function node.

Steps:

  1. Drag and drop a Function node.

  2. Open Function node.

  3. Enter the following function:

    var access_token = msg.payload.access_token

    var refresh_token = msg.payload.refresh_token

    flow.set('at', access_token);

    flow.set('rt', refresh_token);

    var date = new Date();

    msg.date = new Date();

    flow.set('expire', new Date(date.setHours(date.getHours()+1)));

    return msg;

  4. Connect "== 200" of the Switch node to begin of the Function node.

Now we have our token and we can start using it.

 

Call Dynamics 365 with the access token

With our tokens in memory we can call Dynamics 365 Before we start we need to check if the token is still active. We will do this with a Function node.

Steps:

  1. Drag and drop a Function node.

  2. Open Function node.

  3. Enter the following function:

    var date = new Date();

    msg.date = new Date();

    return msg;

 

Next we need to check if our expire time is not past the current time. This is done with a Switch node.

Steps:

  1. Drag and drop a Switch Node.

  2. Open Node:

    1. Change Property to flow.expire

    2. Add an option for if not expired

      >= msg.date

    3. Add the option otherwise for expired

  3. Connect end of the Function node to begin of the Switch Node.

We are going to continue on the not expired flow. The expired flow will continue with chapter Use a refresh token to get a new access token.

 

Our next step is to prepare the request, this is done using a Function node.

Steps:

  1. Drag and drop a Function node.

  2. Open Function node.

  3. Enter the following function:

    Note [Resource] = Dynamics365 Online Instance URL.

    Note In this example we will prepare the incoming uri, so we can use it in the OData url.

    var d365_url = '[Resource]'

    var q = msg.session.sipUri

    if (q.match(RegExp('^(sipThe Session Initiation Protocol (SIP) is a protocol to make multimedia communication (audio, video and other data communication) possible and it is also used for Voice over IP (VoIP). SIP has similarities with other Internet protocols such as HTTP and SMTP.:/+)|^(tel:)|(user=phone)$'))) {

    startindex = q.indexOf("+") + 1

    endindex = q.lastIndexOf("@")

    if (endindex == -1) {

    q = q.substring(startindex)

    } else {

    q = q.substring(startindex, endindex)

    }

    q = "%" + q.substring(q.length - 9).split('').join().replace(/,/g, '%') + "%"

    d365_odata = d365_url + "/api/data/v9.1/contacts?$filter=contains(mobilephone,%27" + q + "%27)%20or%20contains(telephone1,%27" + q + "%27)"

    } else if (q.match(RegExp('^(sip:)'))) {

    startindex = q.indexOf(":") + 1

    endindex = q.lastIndexOf(";")

    if (endindex == -1) {

    q = q.substring(startindex)

    } else {

    q = q.substring(startindex, endindex)

    }

    d365_odata = d365_url + "/api/data/v9.1/contacts?$filter=emailaddress1%20eq%20%27" + q + "%27"

    } else {

    d365_odata = ''

    }

    msg.url = d365_odata

    msg.headers = {

    "Authorization": "Bearer " + flow.get('at'),

    "Accept": "application/json",

    "OData-MaxVersion": "4.0",

    "OData-Version": "4.0"

    };

    return msg;

  4. Connect ">= msg.date" of the Switch node to begin of the Function node.

 

Now that we prepared our message we can send the request. This is done using a HTTP Request node.

Steps:

  1. Drag and drop a http request node.

  2. Open Node:

    1. Method = Post

    2. Return = a parsed JSON object

  3. Connect the end of the Function node to the begin of the HTTP request node.

The output is stored in msg.payload and can be used in the rest of your flow. You can use the following expression to greet the customer by name:

"Hello " & payload.value[0].fullname

 

 

Use a refresh token to get a new access token

When your access token is expired you can generate a new one using the refresh token. We start with a function node.

Steps:

  1. Drag and drop a Function node.

  2. Open Function node.

  3. Enter the following function:

    Note [Resource] = Dynamics365 Online Instance URL. Make sure Encode. Example https%3A%2F%2Fdemo.crm6.dynamics.com%2F

    msg.headers = {

    "Accept": "application/json",

    "Content-type": "application/x-www-form-urlencoded"

    };

    msg.credentials =

    {

    "client_id": "2ad88395-b77d-4561-9441-d0e40824f9bc&",

    "refresh_token": flow.get('rt'),

    "resource": "[Resource]"

    }

    msg.payload = "client_id=" + msg.credentials.client_id + "&refresh_token=" + msg.credentials.refresh_token + "&resource=" + msg.credentials.resource + "&grant_type=refresh_token"

    return msg;

 

Now that we prepared our message we can send the request. This is done using a HTTP Request node.

Steps:

  1. Drag and drop a http request node.

  2. Open Node:

    1. Method = Post

    2. URL = https://login.microsoftonline.com/common/oauth2/token

    3. Return = a parsed JSON object

  3. Connect the end of the Function node to the begin of the HTTP request node.

 

Next we want to check if our output was successful. This can be done with a Switch node.

Steps:

  1. Drag and drop a Switch Node.

  2. Open Node:

    1. Change Property to msg.statusCode.

    2. Add an option for a OK response.

      == 200

    3. Add the option otherwise for any other response.

  3. Connect end of the HTTP request node to begin of the Switch Node.

 

If the response was 200 OK then we can store the tokens. Note that an access token is only valid for one hour, for that reason we also store the expiration time. This can be done with a Function node.

Steps:

  1. Drag and drop a Function node.

  2. Open Function node.

  3. Enter the following function:

    var access_token = msg.payload.access_token

    var refresh_token = msg.payload.refresh_token

    flow.set('at', access_token);

    flow.set('rt', refresh_token);

    var date = new Date();

    msg.date = new Date();

    flow.set('expire', new Date(date.setHours(date.getHours()+1)));

    return msg;

  4. Connect "== 200" of the Switch node to begin of the Function node.

Now we have new access token and we can continue using it.