Signature Validation

The lean.x signature authentication adds an additional security layer for API requests by generating a unique signature for each request. This signature ensures the authenticity and integrity of the requests made to the API. Each signature is valid only for 5 minutes within the timestamp and is tied to the specific API key. Merchants have the option to enable or disable this feature based on their security needs.

Enable or Disable Feature

You may find this feature under API > API Key > Edit API Key > X-Signature. Refer screen shot below as reference.

Flow Process

  1. Message Construction:

    • When the feature is enabled, the system will automatically authenticate every API request send to the system. The signature will be a concatenation of the following elements in this specific order:

      • HTTP_METHOD: The HTTP method used for the request (GET, POST, PUT, DELETE, PATCH).

      • UUID: The unique identifier (UUID) associated with the API key. Can be retrieved from Merchant Portal

      • URL_PATH: The endpoint path of the API request.

      • TIME_STAMP: The current Unix timestamp in seconds.

      • AUTH_TOKEN: The authentication token associated with the API key.Can be retrieved from Merchant Portal

      • NONCE: A unique random number or string, typically a UUID4, to ensure the request's uniqueness.

  2. HMAC Generation:

    • Our system will require your application to generate an HMAC (SHA256) signature of the constructed message using the Hash Key as the secret key , which can be retrieved from Merchant Portal. This HMAC output serves as the X-Signature.

  3. Request Header Injection:

    • The generated X-Signature, along with the timestamp and nonce, is included in the request headers. The headers will include:

      • x-signature: The HMAC-SHA256 signature.

      • x-timestamp: The Unix timestamp used in the signature.

      • x-nonce: The unique nonce used in the signature.

  4. Validation:

    • On the server-side, the received X-Signature is validated by reconstructing the message and comparing the signature with the one received in the header. If they match, the request is authenticated and processed.

Sample Header

A typical API request header with HMAC signature with additional header will look like this

POST /api/v1/merchant/create-bill-page HTTP/1.1
Host: api.leanx.dev
Content-Type: application/json
auth-token : LP-44D9FDC8-MM|f11bb37b-dc4a-45cf-9607d68f31e96e7c.....
x-signature: 23ef4f5c2683c915902c7b2b4f17ecd82ca66d53ed4ec0552ca3b42e7eeebe82
x-timestamp: 1723540529
x-nonce: 45fe2c14-1905-4617-917b-6c50159a1722

This process ensures that each API request is securely authenticated and is valid for a short time, reducing the risk of replay attacks. Merchants should enable this feature to enhance the security of their API transactions.

Resources

This code snippet collection will help you with HMAC generation from your system

const CryptoJS = require('crypto-js')

const UUID = pm.environment.get("UUID");
const AUTH_TOKEN = pm.environment.get("AUTHTOKEN");
const HASH_KEY = pm.environment.get("HASHKEY");

// Define the HTTP method and URL path
const HTTP_METHOD = pm.request.method;
let URL_PATH = pm.request.url.getPath();

// Replace placeholders with actual values
const PLATFORM = "api";
const API_VERSION = "v1";

// Replace placeholders if necessary
URL_PATH = URL_PATH.replace("{{PLATFORM}}", PLATFORM).replace("{{API_VERSION}}", API_VERSION);


// Get the current timestamp in seconds
const TIME_STAMP = Math.floor(Date.now() / 1000);

// Generate a random UUID for the nonce
const NONCE = uuidv4();

// Create the message to be hashed
const message = `${HTTP_METHOD}|${UUID}|${URL_PATH}|${TIME_STAMP}|${AUTH_TOKEN}|${NONCE}`;

// Generate the HMAC signature using SHA256
const hmacSignature = CryptoJS.HmacSHA256(message, HASH_KEY).toString(CryptoJS.enc.Hex);

// Set the headers in Postman
pm.collectionVariables.set("hmac", hmacSignature);
pm.collectionVariables.set("timestamp", TIME_STAMP);
pm.collectionVariables.set("nonce", NONCE);

// Function to generate UUID v4
function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

Last updated