Authentication (Inbound)

Authentication (Inbound)

Servicely supports a number of authentication methods for inbound integrations.

Basic Authentication

Basic authentication is the simplest, but most insecure authentication mechanism. Basic authentication passes a username and password (unencrypted) in the HTTP headers.

Basic authentication can be disabled on an instance by setting the Application Property system.auth.basic.enable to false.

API Token Authentication

API Tokens provide a simple mechanism to provide controlled access to the Servicely APIs, while providing a basic level of control and validation of the authentication process.

API Tokens can be used either with or without a shared secret and request level verification.

Bearer authentication token

Bearer tokens are the simplest form of password-less authentication. Bearer tokens are sent in the HTTP headers of a request, and provide a very simple mechanism to set up an integration with minimal effort.

However, Bearer tokens provide no protection against Man-In-The-Middle (MITM) attacks, and provide no mechanism to validate the identity of the sender, or of the integrity of the message.

Bearer authentication can be disabled on an instance by setting the Application Property system.auth.bearer.enable to false.

 

Bearer authentication token (Provided by URL)

To use this functionality, you need to be on Version 1.10 or later.

An alternate object for bearer tokens is where they are provided via a URL. Such as: http://example.servicely.ai/v1/ITSMWork?token=xxxx.

This is not typically a preferred way, as it does not provide protection against Man-In-The-Middle (MITM) attacks, and provide no mechanism to validate the identity of the sender, or of the integrity of the message.

By default, this is disabled, however, you can enabled it by:

  1. Setting the application property: system.auth.bearer.token.url.enable to true.

  2. Going to the available value table (specifically the following record #/AvailableValue/617185e6bb4211ef937dba899352c358) and making it active.

If you use this mechanism, we strongly suggest utilising the URL Allowed paths field to secure further.

image-20250411-035536.png

HMAC (Hash-Based Message Authentication Codes)

HMAC defines a mechanism to provide validation of both the authentication, and validation of the message structure, based on an API Token and a shared client secret.

Servicely provides two levels of HMAC authentication.

HMAC Header

The HMAC Header scheme provides a simple mechanism to provide an extra layer of validation over Bearer tokens. The HMAC Header validation uses a shared secret key and hashing to validate that authenticity of the sender.

This provides a level of confidence that the message originated from someone who knew the shared secret (i.e. protects against some MITM attacks); however, it does not provide any validation that the message structure was received unmodified.

Testing with Postman

Create a request and use the following ‘Pre request script’ to set up the HMAC Header authentication:

// This is your Token and Shared Secret let token = "GX8jOYNTBVOP9.ClTZMnYtSVK2tnVBwu7AmwYFrrOA7K24"; let sharedSecret = "l9YDdAoNg7CbUclGmgIvTyuELHwCIGfy"; // Set the date as the UTC String format let formattedDate = (new Date()).toUTCString(); // Hash the date with Hmac256 and Base64 the result let hashedDate = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(formattedDate, sharedSecret)); // Add the Date Header pm.request.headers.upsert({ key: "Date", value: formattedDate }); // Add the Authorization Header pm.request.headers.upsert({ key: "Authorization", value: "HMAC " + token + ":" + hashedDate });

Multiple Header Support

Servicely can perform the HMAC hash on multiple headers, allowing you to customise the level of validation of the message.

In the System API Token Definition, the header fields can be specified in the ‘Header key’ field (comma separated).

Specify custom Header keys for HMAC headers

On the client side, the HMAC needs to be calculated on all of the header values concatenated with a colon character (:).

Below is an example Postman script to work with the above example:

// This is your Token and Shared Secret let token = "nNeYPRes5YJW3.CVULtz1Po5c3euFNGn4Ss2bmZDnhbQgb"; let sharedSecret = "5Bnd61NFV58fOQNmiopjJA1eDlrBiwzW"; // This is an example of hashing multiple fields let customValue = pm.variables.replaceIn('{{$guid}}') // Set the date as the UTC String format let formattedDate = (new Date()).toUTCString(); // The complete string to hash let toHash = formattedDate + ":" + customValue; // Hash the date with Hmac256 and Base64 the result let completeHash = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(toHash, sharedSecret)); // Add the Date Header pm.request.headers.upsert({ key: "Date", value: formattedDate }); // Add the Custom Header (in Servicely, specify the 'Header Key' = [Date,X-Custom]) pm.request.headers.upsert({ key: "X-Custom", value: customValue }); // Add the Authorization Header pm.request.headers.upsert({ key: "Authorization", value: "HMAC " + token + ":" + completeHash });

HMAC Body

The HMAC Body scheme combines hashing of both the authorisation (API Token) and of the content of the message body and headers. This provides the ability to validate both authenticity (the message is from a trusted party) and integrity (that the message has not been altered in transit) of the request.

The Amazon Web Services (AWS) APIs are a high profile example of an API that uses this authentication scheme.

HTTP requests will be signed with a shared secret key using HMAC. The string to sign format is:

<Method>\n <Content-MD5>\n <Content-Type>\n <Date>\n <URL>

Example String-to-sign

POST vVqHE1k/uBRCoWe0FAh95g== application/json Tue, 12 Jan 2016 14:57:28 GMT /v1/Incident

Example Authorization Header with HMAC signature

Authorization: HMAC dpKlK3jCJDGnZ.WT5ZfsfdpJaJltJCGUDq8F6BBzkytqBm:smoXggvWWJjMlt4sWtyH9qb5r/boQUjRB6jRWEcnWvM=

 

Testing with Postman

Create a request and use the following ‘Pre request script’ to set up the HMAC authentication:

// This is your Token and Shared Secret let token = "dpKlK3jCJDGnZ.WT5ZfsfdpJaJltJCGUDq8F6BBzkytqBm"; let sharedSecret = "XhwrFK236jz1mJo1skgT4h4OQvyP5Cji"; // Set the date as the UTC String format let formattedDate = (new Date()).toUTCString(); // Ensure the Content Type is set let contentType = "application/json" let SEPARATOR = "\n"; // Newline separator let bodyMD5 = ""; // If the request has a body, we need to MD5/Base64 it if (pm.request.body.toString() != "") { bodyMD5 = CryptoJS.enc.Base64.stringify(CryptoJS.MD5(pm.request.body.toString())); } // Then build the message to sign in this format let stringToSign = request.method + SEPARATOR + bodyMD5 + SEPARATOR + contentType + SEPARATOR + formattedDate + SEPARATOR + pm.request.url.getPath(); // HMAC SHA256 and Base64 the body string using the shared secret let signed = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(stringToSign, sharedSecret)); // Add the Date Header (ensure it is present and the same as the signed copy) pm.request.headers.upsert({ key: "Date", value: formattedDate }); // Ensure the content type is present pm.request.headers.upsert({ key: "Content-Type", value: contentType }); // If we have a body, add the Content-MD5 header if (bodyMD5 != "") { pm.request.headers.upsert({ key: "Content-MD5", value: bodyMD5 }); } // Finally, add the Authorization Header pm.request.headers.upsert({ key: "Authorization", value: "HMAC " + token + ":" + signed });

Generating API Tokens

To generate a System API Token, navigate to Administration → Integration → System API Tokens → New.

Fill in the mandatory fields (Name, Validation type, Hash method, Impersonate User), and Click the ‘Generate token’ button.

A new Token and Secret will be generated and displayed. It is important to copy this information and store it somewhere safe. The information can not be regenerated on the Servicely side to ensure no one can ever get the information required to authenticate from the application (the Token itself is hashed and never stored - Servicely only stores the Token prefix before the dot).

Restricting Token Use

New in 1.9: As part of the token setup, you can also restrict which URL paths the token can be used for. Such as, if the token is for a specific integration, you can restrict the token to only be accessible with path. Note that if it has not been populated, the token will be usable based on the impersonated user’s normal permissions and restrictions. An example of this is populating it with /controller/ControllerName, so the token can only be used for that controller. Note that if you want multi paths here, you can comma separate it, such as /controller/ControllerName,/controller/BiDirectionalIncidentVendorController.

Servicely Documentation