Connecting to SBA (Service Based Architecture) endpoints for Dynamics GP is not complex, but it does have a couple of steps that are required by SBA and may not be intuitive even to someone who has substantial experience working with REST endpoints. In this article, we will cover an end-to-end scenario of how to build a JavaScript module that can be used for creating a secure connection to SBA. Ideally, what you will see here should be generic enough that you can reuse it across a number of your applications. You should even be able to reuse this module for applications that run on different platforms. The goal here is to build it once and use it on any number of applications across all platforms that support JavaScript apps.

 

Here is a sample way to communicate to an instance of SBA endpoint:

SBA authentication model

SBA supports three authentication modes – Azure Active Directory, NTLM, and Basic Auth. In this article we will focus on how to build a communications module using Basic Auth. This allows us to create a reusable module in JavaScript that requires absolutely no modifications when used across Windows, iOS, and/or Android platforms.

If you have not already done so, please read this great article that describes in more details how SBA authentication works.

Step 1: Creating a generic JavaScript module

Let’s create a module that will be responsible for handling communications with SBA. To start, we have a JavaScript module, called Communications, which has just one method - sendRequestAsync:

var Communications = (function () {

   var sendRequestAsync = function (sendBody) {

   };

  return {

       sendRequestAsync: sendRequestAsync,

   };

})();

The purpose of this structure is to create a module that can be called anywhere in the application by simply doing this:

Communications.sendRequestAsync(requestInfo);

 

Step 2: Create the authentication API (stub out needed functions)

It is time to add a few details to our Communications module. First, let’s define the structure of the actual http request in the body of sendRequest method. In this example we chose to use jQuery library to help us, but you can use any other library that has API for making an http request…

 

  var Communications = (function () {

   var sendRequestAsync = function (sendBody) {

       return $.ajax({

           url: "https://mySBAEndpointServer/GPService/Tenants(GP%202015 SBADEMO)/Companies(Fabrikam,%20Inc.)/Help",

           type: "GET",type: "GET",

           accepts: { json: "application/json, text/javascript, */*" },

           dataType: "json",

           contentType: "application/json",

           headers: {"Authorization":"Basic SGVsbG8gV29ybGQ=="},

           data: sendBody && Object.keys(sendBody).length ? JSON.stringify(sendBody) : null

       });

   };

   return {

       sendRequestAsync: sendRequestAsync,

   };

})(); 

This is a pretty simple example. And, as you can already see, not very useful. It can only do one operation, and if you wanted to change a user, you would have to redeploy your app. Obviously, nobody should be doing that for a real app. Let’s change that a little by adding a configuration object. It will be passed into our Communication module during runtime.

var Communications = (function () {

  
   var buildUrl = function(options) {

       var result = "";

       result += options.baseUrl;

       result += "/Tenants(" + options.tenant + ")";

       result += "/Companies(" + options.company + ")";

       result += "/" + options.action;

       return result;

   };

   var buildHeader = function(config) {

       var base64Auth = "SGVsbG8gV29ybGQ=="; //This is an example. Insert encoding utility here

       return {

           "Authorization": "Basic " + base64Auth

       };

   };

   var sendRequestAsync = function (config, sendBody) {

       return $.ajax({

           url: buildUrl(config),

           type: config.verb || "GET",

           accepts: { json: "application/json, text/javascript, */*" },

           dataType: "json",

           contentType: "application/json",

           headers: buildHeader(config),

          data: sendBody && Object.keys(sendBody).length ? JSON.stringify(sendBody) : null

       });

   };

   return {

       sendRequestAsync: sendRequestAsync,

   };

})();


Usage:

Here is example of how this could be consumed:

//Usage:

var config = {

   baseUrl: "https://mySBAEndpointServer/GPService",

   tenant: "GP%202015 SBADEMO",

   company: "Fabrikam,%20Inc.",

   action: "Help",

   verb: "GET",

   userName: "testUser ",

   password: "Hello World",

};

Communications.sendRequestAsync(config);

 
var sendBody = {}; //define the body of this action, based on your SBA API

config.verb = "POST";

config.action = "Applicants"

Communications.sendRequestAsync(config, sendBody);


Step 3: UTF-8 encoding

 

All the information of the http request must be in UTF-8 format. According to ECMA specifications for string, string data type in JavaScript is represented by a sequence of 16-byte integer values (often in UTF-16 format, but not guaranteed). SBA expects all data that it handles to be in UTF-8 format. For that reason, we need to convert (or verify) data in outgoing messages into proper format.  

Step 4: Base64 encoding

 

You probably already noticed that we include a headers attribute in the call. This is how we tell the SBA endpoint that we are who we say we are (authentication) and that we have permissions to do what we are doing (authorization)… In the header you will notice a JSON element what contains Authorization key that is set to Basic, followed by some string. Keyword Basic tells the server to expect a basic authentication format, followed by the user name and password. User name and password have to be supplied in Base64 encoded format. Although, it is very difficult for a human to read, it is important to remember - THIS IS NOT ENCRYPTION. It is still sent in a plain text. This is why it’s imperative that you always use SSL on your instances of SBA endpoints.  

Step 5: Suggestions for making it portable (reusable)

               The simplest way to add this code to your application is to copy-paste it to one of your JavaScript files and just run it… However, it is far from the best practice. A much better approach is to encapsulate your code in a separate file that gets included in your project. If you keep this module as generic as it is shown here, you can very easily reuse the same file across a number of other projects without making a single change in the code. It is always a good idea to keep your code modular, with the least possible coupling to the rest of the application. Think of it as another library that you imported in your project, like jQuery. This also allows you to create good unit test coverage of the module without instantiating the rest of your application. Isolation is one of your best friends when working with JavaScript apps.

               For those of you working with Cordova or PhoneGap, consider creating a reusable plugin for the purpose of communicating with SBA. Another great opportunity here is to submit your plugin to Cordova or PhoneGap and allow the power of the open source community help you stabilize it and add features that you may not have time (or immediate need) to implement yourself.