Authentication and Authorization

  • Updated

Authentication and authorization is based on an authorization header in combination with other request headers. A signature, part of the authorization header, has to be calculated for each request.

To be able to make the request you need the following information about your installation. Ask your contact person at Liana Technologies if you don’t have these:

  • API User ID
  • API Secret
  • API Realm
  • API Url

Required Headers

For every request to succeed we require the following headers:

Authorization

The requests are authorized with an authorization header. This header consists of 3 parts:

  • Realm: The realm is a string of capital letters, defined by the domain of your LianaAutomation installation.
  • User id: This is a unique ID for your API user (and only works with one installation).
  • Signature: A signature that is calculated with other variables, explained below.

The parts are combined as follows:

{Realm} {User id}:{Signature}

Example of an Authorization header

Authorization: LCUI 1:d79ffb8112a62fb8af166cedfb96164ee7d2f3d6fea9669cd3b40f52ca69692f

Date

The date header must contain a computer readable timestamp format. Using ISO 8601 is recommended. The timestamp can be maximum 15 minutes old. You could for example launch multiple requests with the same timestamp for 15 minutes.

Example of a Date header:

Date: 2021-09-14T15:28:09+03:00

Content-md5

This header contains the md5 hash of the request body

Example of a Content-md5 header:

Content-md5: 344aab9758bb0d018b93739e7893fb3a

Content-Type

The content of the requests should be of type application/json

Example of the Content-Type header:

Content-Type: application/json

Signature

The authorization header signature is generated using HMAC with SHA-256 algorithm.

The key for HMAC is the REST user password and the message is constructed in the following way:

  • Create a UTF-8 encoded string with UNIX style line endings (\n).
  • Every item on it's own line, add to the string:
    • Request method: This is POST for all our endpoints
    • Content-md5: The value of the Content-md5 header 
    • Content-Type: The value of the Content-Type header
    • Date: The value of the date header
    • Content: The full content body of the request
    • PATH: The path part of the URI, including query parameters if any.
Example 
POST
344aab9758bb0d018b93739e7893fb3a
application/json
2021-09-14T15:28:09+03:00
{"ping":"pong"}
/rest/v1/pingpong

signaturecontent = POST\n344aab9758bb0d018b93739e7893fb3a\napplication/json\n2021-09-14T15:28:09+03:00\n{"ping":"pong"}\n/rest/v1/pingpong
    
HMAC_SHA256("password", signaturecontent)
= d79ffb8112a62fb8af166cedfb96164ee7d2f3d6fea9669cd3b40f52ca69692f

 

Code Samples

To test your connection you can use any of the following provided code samples that use our pingpong endpoint. 

PHP 

<?php

/**
 * Account specific variables.
 *
 * These variables are given to you by or can be requested from your contact person at Liana Technologies.
 */
$user   = "USER ID";          // The user id, integer
$secret = "USER SECRET";      // An hexadecimal secret string
$url    = "REST API URL";     // The base url for your API installation
$realm  = "REST API REALM";   // The realm of your API installation, all caps alphanumeric string

/**
 * General variables
 */
$basePath    = 'rest';             // Base path of the api end points
$contentType = 'application/json'; // Content will be send as json
$method      = 'POST';             // Method is always POST

/**
 * Send a API request to LianaAutomation
 *
 * This function will add the required headers and calculates the signature for the authorization header
 *
 * @param string $path             The path of the end point
 * @param array  $data             The content body (data) of the request
 * @return mixed
 */
function send(string $path, array $data) {
	// Import variables
	global $user, $secret, $url, $realm, $basePath, $contentType, $method;
	// Encode our body content data
	$data = json_encode($data);
	// Get the current datetime in ISO 8601
	$date = date('c');
	// md5 hash our body content
	$contentMd5 = md5($data);
	// Create our signature
	$signatureContent = implode(
		"\n",
		[
			$method,
			$contentMd5,
			$contentType,
			$date,
			$data,
			"/{$basePath}/{$path}"
		],
	);
	$signature = hash_hmac('sha256', $signatureContent, $secret);
	// Create the authorization header value
	$auth = "{$realm} {$user}:" . $signature;

	// Create our full stream context with all required headers
	$ctx = stream_context_create([
		'http' => [
			'method' => $method,
			'header' => implode(
				"\r\n",
				[
					"Authorization: {$auth}",
					"Date: {$date}",
					"Content-md5: {$contentMd5}",
					"Content-Type: {$contentType}"
				]
			),
			'content' => $data
		]
	]);

	// Build full path, open a data stream, and decode the json response
	$fullPath = "{$url}/{$basePath}/{$path}";
	$fp = fopen($fullPath, 'rb', false, $ctx);
	$response = stream_get_contents($fp);
	$response = json_decode($response, true);
	return $response;
}

// Example usage:
$a = send(
	'v1/pingpong',
	[
		'ping' => 'pong'
	]
);
var_dump($a);

Node (JavaScript) 

/**
 * Dependencies
 *
 * We use the CryptoJS library for hashing and fetch for making the http call
 */
import md5 from 'crypto-js/md5.js';
import hmacSHA256 from 'crypto-js/hmac-sha256.js';
import fetch from 'node-fetch';

/**
 * Account specific variables.
 *
 * These variables are given to you by or can be requested from your contact person at Liana Technologies.
 */
var user   = "USER ID";          // The user id, integer
var secret = "USER SECRET";      // An hexadecimal secret string
var url    = "REST API URL";     // The base url for your API installation
var realm  = "REST API REALM";   // The realm of your API installation, all caps alphanumeric string

/**
 * General variables
 */
var basePath    = 'rest';             // Base path of the api end points
var contentType = 'application/json'; // Content will be send as json
var method      = 'POST';             // Method is always POST

async function send(path, data) {
	// Format object to string
	data = JSON.stringify(data);
	// Get the current datetime in ISO 8601
	let date = new Date().toISOString();
	// md5 hash our body content
	let contentMd5 = md5(data).toString();
	// Create our signature
	let signatureContent = [
		method,
		contentMd5,
		contentType,
		date,
		data,
		'/' + basePath + '/' + path
	].join('\n');
	let signature = hmacSHA256(signatureContent, secret).toString();

	// Create the authorization header value
	let auth = realm + ' ' + user + ':' + signature;

	// Build the full path and create our request with all required headers
	let fullPath = url + '/' + basePath + '/' + path;
	let response = await fetch(fullPath, {
		"method": method,
		"headers": {
			"Authorization": auth,
			"Date": date,
			"Content-md5": contentMd5,
			"Content-Type": contentType
		},
		"body": data
	});

	// Return the response
	return response.json().then(res => {
		return res;
	});
}

// Example usage
send('v1/pingpong', {"ping":"pong"}).then((data) => {
	console.log(data);
});

Postman

You can also use Postman to create the authorization header.

  • Create a new Collection
  • Place the below script in the collection’s ‘Pre-requist Script’ tab
  • Add the required variables to the collection’s ‘Variables’ tab
  • Create a new POST request to the API url given to you, followed by /rest/v1/pingpong
  • Use {“ping”:”pong”} as body content. Make sure the content is marked as raw of type JSON
Pre-Request Script 
/**
 * - Create a new collection to paste this script as Pre-request Script
 * - Set following account specific variables in the Variables tab of your Collection.
 *   These variables are given to you by or can be requested from your contact person at Liana Technologies.
 * user
 * secret
 * realm
 */

// General variables
var contentType = 'application/json';

// Dynamically fetched variables from the request
var method = pm.request.method.toUpperCase();
var data = pm.request.body.toString();
var path = pm.request.url.getPath();

// Get the current datetime in ISO 8601
var date = new Date().toISOString();
// md5 hash our body content
var contentMd5 = CryptoJS.MD5(data).toString();

// Create our signature
var signatureContent = [
	method,
	contentMd5,
	contentType,
	date,
	data,
	path
].join('\n');
var signature = CryptoJS.HmacSHA256(signatureContent, pm.variables.get("secret")).toString();
// Create the authorization header value
var auth = pm.variables.replaceIn("{{realm}} {{user}}:") + signature;

// Add headers
pm.request.headers.add({
	key: "Authorization",
	value: auth
});
pm.request.headers.add({
	key: "Date",
	value: date
});
pm.request.headers.add({
	 key: "Content-md5",
	 value: contentMd5
});

 

 
 

 

 

Was this article helpful?

0 out of 0 found this helpful

Comments

0 comments

Article is closed for comments.