> For the complete documentation index, see [llms.txt](https://docs.leanx.io/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.leanx.io/api-docs/signature-validation.md).

# 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.&#x20;

<figure><img src="/files/NPVBB6kG7ZHlKOz5VLN2" alt=""><figcaption><p>Enabling or Disabling Signature Validation Feature</p></figcaption></figure>

## 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

{% tabs %}
{% tab title="Postman Script" %}

```javascript
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.request.headers.add({key: "x-signature",value: hmacSignature});
pm.request.headers.add({key: "x-timestamp",value: TIME_STAMP});
pm.request.headers.add({key: "x-nonce",value: 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);
    });
}

```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

class LeanxSignatureGenerationAdapter
{
    public static function generateSignature($UUID, $AUTH_TOKEN, $HASH_KEY, $HTTP_METHOD, $URL_PATH)
    {
        // Replace placeholders with actual values
        $PLATFORM = "api";
        $API_VERSION = "v1";

        // Replace placeholders in the URL path
        $URL_PATH = str_replace("{{PLATFORM}}", $PLATFORM, $URL_PATH);
        $URL_PATH = str_replace("{{API_VERSION}}", $API_VERSION, $URL_PATH);

        // Get the current timestamp in seconds
        $TIME_STAMP = time();

        // Generate a random UUID for the nonce
        $NONCE = self::generateUuidV4();

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

        // Generate the HMAC signature using SHA256
        $hmacSignature = hash_hmac('sha256', $message, $HASH_KEY);

        // Return the headers
        return [
            'x-signature' => $hmacSignature,
            'x-timestamp' => $TIME_STAMP,
            'x-nonce' => $NONCE
        ];
    }

    private static function generateUuidV4()
    {
        return sprintf('%04x%04x-%04x-4%03x-%04x-%04x%04x%04x',
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0x0fff) | 0x4000,
            mt_rand(0, 0x3fff) | 0x8000,
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
        );
    }
}
```

{% endtab %}
{% endtabs %}
