Authentication

Prerequisites

Before you can start the Authentication process, you need a private secret key and a Partner ID. Both will be provided to you by LINK Mobility AS.

The Authentication process consists of three steps:

  1. First you concatenate several pieces of information into a single message string.

  2. Then you take that string and create a HMAC (Hashed based Message Authentication Code). The basic idea is to take the message and a private secret key and hash them together using SHA256 to create a unique "signature" that is used to verify the integrity and authentication of the request, and ensures that the data has not been tampered with. When the request is received by Link Mobility, the server will create a signature using the same algorithm and compare the result. If the two signatures don't match the request will be denied. Because the secret key used to create the HMAC is only known between you and Link Mobility, it is impossible for anyone else to reproduce the signature.

  3. The final step is to compose a HTTP Authorization header consisting of several pieces of information, including the first 10 characters of the HMAC signature created in the previous step. This header must be included with each HTTP request in order for the request to be authenticated.
 Click here to see details about how to compose the HMAC header

Step 1 - Generating the string to be signed

Signature partsHow to generate
Partner IDAs provided by Link Mobility, For example 123.
HTTP MethodThe HTTP Method of the request in upper case. For example "POST", "GET", "PUT"
URLThe absolute URI of the request, including any query parameters. Lower cased, then URL-encoded. Make sure the special characters of the URL-encoded string are in upper case. For example %3A, not %3a.
TimestampUNIX time, the number of seconds since Epoch UTC (January 01, 1970).  For example 1472195737 which corresponds to 2016-08-26T07:15:37+00:00 in ISO-8601.
NonceAn reference identifier of your choice, such as a GUID. Max 50 chacters and must be unique per request.
ContentIf there is a payload/body on the request, MD5-hash it first and then base64-encode the result.

All of the above parts are concatenated into one string. Make sure the resulting string is UTF8 encoded.

Sample string

123POSThttp%3A%2F%2Fpay-core.linkmobility.com%2Fapi%2Ftransactions147219695557bff15b4ecf0yWCdBDtoj/Vb8BE3VqHPtg==

Step 1 - Generating the string to be signed

Signature partsHow to generate
Partner IDAs provided by Link Mobility, For example 123.
HTTP MethodThe HTTP Method of the request in upper case. For example "POST", "GET", "PUT"
URLThe absolute URI of the request, including any query parameters. Lower cased, then URL-encoded. Make sure the special characters of the URL-encoded string are in upper case. For example %3A, not %3a.
TimestampUNIX time, the number of seconds since Epoch UTC (January 01, 1970).  For example 1472195737 which corresponds to 2016-08-26T07:15:37+00:00 in ISO-8601.
NonceAn reference identifier of your choice, such as a GUID. Max 50 chacters and must be unique per request.
ContentIf there is a payload/body on the request, MD5-hash it first and then base64-encode the result.

All of the above parts are concatenated into one string. Make sure the resulting string is UTF8 encoded.

Sample string

123POSThttp%3A%2F%2Fpay-core.linkmobility.com%2Fapi%2Ftransactions147219695557bff15b4ecf0yWCdBDtoj/Vb8BE3VqHPtg==

Figure 1 - create message string




Step 2 - Signing the Message

  1. Take the message string created in Step 1
  2. Take your private secret key
  3. Hash them together using HMAC-SHA256 (choose raw binary output)
  4. Base64-encode the result
Sample HMAC signature
2FBhBLpuQt9GsXiVI1bMA0dsqEJbEsw4lk3l1G+QLfY=

Step 3 - Compose Authorization header

You concatenate some of the values from Step 1 and the first 10 characters of the signature from Step 2 and add to the Authorization header with the parts separated by :  in the following order


Authorization header partsHow to generate
Partner IDAs provided by Link Mobility, For example 123.
SignatureThe first 10 characters of the HMAC signature created in Step 2.
NonceYour unique reference ID from Step 1.
TimestampThe same Unix timestamp from Step 1.


Sample Authorization header
Authorization: hmac 123:2FBhBLpuQt:57c08f8dccc59:147223745

Figure 2 - HMAC signing and compose Authorization header DIAGRAM




Sample C# code for generating the header:

static void Main()
{
	var secretkey = "<your base-64 encoded secret key here>";
	var partnerId = 1;
	var url = "https://pay-core.linkmobility.com/api/transactions/1/1234";
	var method = "GET";
	var timestamp = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds);
	var nonce = Guid.NewGuid().ToString("N");
	var data = partnerId + method + WebUtility.UrlEncode(url.ToLower()) + timestamp + nonce;

	using (var hmac = new HMACSHA256(Convert.FromBase64String(secretkey)))
	{
		var fullHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
		var signedHash = Convert.ToBase64String(fullHash).Substring(0, 10);
		var authHeaderValue = string.Format("hmac \"{0}:{1}:{2}:{3}\"", partnerId, signedHash, nonce, timestamp);
		Console.WriteLine("Authorization: hmac \"{0}\"", authHeaderValue);
	}
}

Sample php code for generating hmac header

<?php
 
$partner_id = '<your partner id>';
$secret_key = '<your secret key>';
$secret_key = base64_decode($secret_key);
 
$request_method = strtoupper("GET");
$url = 'https://TODO/api/action';
$url = strtolower($url);
$request_content = '';
 
$auth_header = getAuthHeader($partner_id, $secret_key, $request_method, $url, $request_content);
echo $auth_header;  // display the Authorization: header to be included in the request
 
 
function getAuthHeader($partner_id, $secret_key, $request_method, $url, $request_content) {
        $requestUri = urlencode($url);
        $requestTimeStamp = time(); // current UNIX timestamp      
        $nonce = uniqid(); // string
         
        if ( !empty($request_content) ) {
            $requestContentMd5Hash = md5($request_content, true); /* raw binary format with length of 16 */
        } else {
            $requestContentMd5Hash = $request_content;
        }
 
        $request_content = base64_encode($requestContentMd5Hash);
        $signatureRawData = ($partner_id . $request_method . $requestUri . $requestTimeStamp . $nonce . $request_content );
 
        $hmac_before_base64 = hash_hmac ( 'sha256', $signatureRawData , $secret_key, true ); // not raw digital output
        $hmac_base64_encoded = base64_encode ( $hmac_before_base64); 
        $hmac_substringed = substr ( $hmac_base64_encoded, 0, 10);
        $auth_header = "hmac $partner_id:$hmac_substringed:$nonce:$requestTimeStamp";
         
        return $auth_header;
}
?>


 Sample python code for generating hmac header (CODE NOT VERIFIED!)
import uuid
import base64
import hashlib
import hmac
import time
import urllib
 
class LinkNext:
	api_root = 'https://pay-core.linkmobility.com/api/'
    	partnerid = None
    	hmac_key = None

	def __init__(self, partnerid, hmac_key):
		self.partnerid = partnerid
	    	self.hmac_key = hmac_key.decode('base64')


	def _generateHMAC(self, uri, http_verb, request = None):
		nonce = uuid.uuid4().hex
		string_timestamp = str(int(time.time()))

    	requestmd5 = ""
	    url_encoded = urllib.quote_plus(uri.lower())

    	if(request):
	    	request_json = json.dumps(request)
    	   	request_bytes =  request_json.decode('utf-8')
        	requestmd5 = hashlib.md5(request_bytes).digest().encode('base64').strip()

		signature_string = '{0}{1}{2}{3}{4}{5}'.format(str(self.partnerid), http_verb, url_encoded, string_timestamp, str(nonce), requestmd5)

		hmac_signature = hmac.new(self.hmac_key, signature_string, hashlib.sha256)

	    base64_hmac_signature = hmac_signature.digest().encode('base64')
    	    hmac_header = '\"{0}:{1}:{2}:{3}\"'.format(str(self.partnerid), base64_hmac_signature[:10], nonce, string_timestamp)
	    header = {'Authorization': 'hmac {0}'.format(hmac_header)}

    	return header
 Sample node.js for generating hmac header (CODE NOT VERIFIED!)
const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');
 
var hmac = generateHmacHeader('<your-secret-key>',12640,'POST','https://test-paycore.azurewebsites.net/api/pre-transactions?api-version=2.0',
'{"amount": 529, "currency": "NOK", "partnerId": 12640, "paymentProviders": ["Nets", "NetsVipps", "Vipps"]}')
 
console.log(hmac);
 
function generateHmacHeader(sharedSecret, partnerId, httpVerb, uri, requestPayload) {  
    var nonce = uuidv4();
    var timestamp = Math.floor(new Date().getTime() / 1000);
    var md5Content = '';
    if (requestPayload) {
        md5Content = crypto.createHash('md5').update(requestPayload).digest("base64");
    }     
      
    var signatureString = partnerId + httpVerb + encodeURIComponent(uri.toLowerCase()) + timestamp + nonce + md5Content;
                 
    var hmacSignature = crypto.createHmac('SHA256', new Buffer.from(sharedSecret, 'base64'))
                                .update(signatureString, 'utf8')
                                .digest('base64');  
        
    return 'hmac ' + [partnerId, hmacSignature.substring(0, 10), nonce, timestamp].join(':');
}

Error codes

Code
Result
401 Hmac timestamp clock-drift too high

The timestamp used to generate the hmac token is too old. It can be max 10 minutes old.

401 Invalid HMAC
The hmac token in the Authorization header has some invalid content.

Sample Request

GET /api/campaigns HTTP/1.1
HOST: pay-core.linkmobility.com
Authorization: hmac "1:95onwB16zB:57c44d452af4e:1472482629"
Content-Type: application/json

Sample Response 

HTTP/1.1 200 OK
Content-Length: 796
Content-Type: application/json; charset=utf-8
...

[{"campaignId":1,"returnUrl":"http://dummy","statusCallbackUrl":"http://dummy","smsStatusCallbackUrl":"http://dummy","smsNotificationOriginator":"2012","smsNotificationText":"Hello","smsReceiptText":"Thank you","shortCode":"2012","currency":"NOK"},

Feeling lost? Click on this link! Portal page