Web service basic authentication

This article describes how to authenticate a Web Service call with a user/password combination. This method is known as basic authentication.

Configuring the web server in HTTPS mode

Basic authentication works by sending a user login and password to the server. The password is encoded (in base64) but not encrypted so this method should never be used over an unencrypted communication channel like HTTP.

You may use HTTP in a test environment but you must must configure the SAFE X3 web server (aka. Syracuse server) in HTTPS mode in your production environment. The procedure is described here.

Enabling basic authentication

Two steps are necessary to enable basic authentication:

First, you need to enable basic authentication in your server's nodelocal.js configuration file. This is done in the session section, which should look like:

CODECODE CODEjavascript
    session: {
        // interactive session timeout (minutes).
        timeout: 20,
        // more session settings ...
        // ...
        // authentication modes
        auth: ["basic"],
        // realm
        realm: "acme",
    },

In this configuration only basic is enabled. You can enable several modes, by separating them with commas. For example: auth: ["basic", "oauth2"].

The realm is an optional setting. It should reflect the name of your organization. If omitted, it defaults to "Syracuse".

The next step is to configure a user on behalf of whom the web service calls will be executed. This user must be configured with basic authentication and must be mapped to a Sage X3 user with an appropriate security profile. See the user administration documentation for details.

Calling a Web Service with basic authentication

Authenticating a web service request with basic authentication is relatively easy. All you need is an Authorization header with a token containing the word Basic followed by a space and the base 64 encoding of user:password. The following JavaScript (node.js) function produces this token:

CODECODE CODEjavascript
function basicToken(login, password) {
    return "Basic " + new Buffer(login + ":" + password).toString("base64");
}

Now you can use this function to call a web service. For example, with streamline.js and the ez-streams library, you would write:
CODECODE CODE javascript
var ez = require('ez-streams');
var login = "johndoe";
var password = "hard2see"; // of course, you should never do this (embed password in source file)
// reads a list of customers
function listCustomers(_) {
    // replace myserver and MYENDPOINT by your server and endpoint names.
    var response = ez.devices.http.client({
        url: "http://myserver:8124/api1/x3/erp/MYENDPOINT/BPCUSTOMER?representation=BPCUSTOMER.$query",
        method: "GET",
        headers: {
            authorization: basicToken(login, password),
        },
    }).end().response(_);
    if (response.statusCode !== 200) throw new Error("request failed with status " + response.statusCode);
    return JSON.parse(response.readAll(_));
}
// Call listCustomers and display the customer code (BPCNUM) and name (BPCNAM) for each one.
var result = listCustomers(_);
// result is not an array but a small envelope object. The array is in result.$resources 
result.$resources.forEach(function(res) {
    console.log(res.BPCNUM + ":\t" + res.BPCNAM);
});

Notes:
  • our examples are written with streamline.js and ez-streams because these tools help keep the code simple. But you could as well write this code with a library of your choice (https://github.com/request/request for example).
  • the query does not return all records from the BPCUSTOMER table, only a first page of 20 records. See the paging article for more information.