Skip to main content

HTTP Signature for Webhooks

When receiving webhooks, it's important to verify that the payload is sent by a trusted source and has not been tampered with. This is commonly achieved by using an HTTP signature, where the sender signs the payload using a secret key and a hashing algorithm (e.g., SHA256). The receiver can then verify the signature using the same secret key.


How HTTP Signature Works​

  1. Sender Side (Webhook Provider):

    • The payload (usually the request body) is hashed using HMAC with SHA256 and a shared Webhook Secret Key.
    • The resulting signature is sent in a header (HTTP-WEBHOOK-SIGNATURE).
  2. Receiver Side (Your Server):

    • Upon receiving the webhook, your server computes the HMAC SHA256 hash of the received payload using the same Webhook Secret Key.
    • It compares the computed signature with the one provided in the header.
    • If they match, the payload is authentic.

Where to find your Webhook Secret Key​

You can retrieve your Webhook Secret Key in the Dashboard:

  1. Go to Dashboard β†’ Developer β†’ Authentication β†’ Webhook tab.
  2. Copy the key from the field Webhook secret key.
  3. Use this key to generate and verify signatures.

Webhook secret key location


Example: Generating & Verifying HTTP Signature​

const crypto = require('crypto');

function generateSignature(payload, webhookSecretKey) {
return crypto
.createHmac('sha256', webhookSecretKey)
.update(payload, 'utf8')
.digest('hex');
}

// Example usage:
const payload = JSON.stringify({ foo: 'bar' });
const webhookSecretKey = 'your_webhook_secret_key_here';
const signature = generateSignature(payload, webhookSecretKey);
console.log('Signature:', signature);

// Verifying
const receivedSignature = req.headers['HTTP-WEBHOOK-SIGNATURE'];
const expectedSignature = generateSignature(req.rawBody, webhookSecretKey);

if (receivedSignature === expectedSignature) {
// valid
} else {
// invalid
}

Note: Always use the raw request body for signature verification. Any modification (e.g., parsing and re-stringifying JSON) may result in signature mismatch.


Testing Guide: How to Verify HTTP Signature​


1. Capture Webhook Request​

  • Open the request log.

  • Copy the Raw Body JSON payload from the webhook request.

    Webhook Site

    Example:

    {
    "uuid": "44QU0367",
    "name": "Hello Clever",
    "email": "test@example.com",
    "external_id": null,
    "status": "waiting",
    "pay_code": {
    "qr_string": "00020101021238610010A000000727013100069704520117101050696623331910208QRIBFTTA53037045405100005802VN62460113B00OCDRJ8YULO0505PGVQR0816TT BWIGBT0BCTYTZ630423BC",
    "bank_information": {
    "bank_name": "TMCP KiΓͺn Long (Kienlongbank)",
    "account_number": "101050696623331",
    "account_name": "AABB",
    "branch_name": "TP.Hα»“ ChΓ­ Minh",
    "description": "Test Payin",
    "swift_code": "KLBKVNVX"
    },
    "message": "Approved by financial institution"
    },
    "currency": "VND",
    "amount": "10000.0",
    "total": "10000.0",
    "paid_amount": "10000.0",
    "is_refundable": false,
    "payment_method": "vn_vietqr_vnd",
    "expired_at": "2025-12-23T06:00:00.000+0000",
    "webhook_notification": {
    "endpoint_url": "https://webhook.site/d6b85f1a-5988-42fb-9dac-88e560bdc08e",
    "authorization_header": "****"
    },
    "status_text": "Payment has been approved, awaiting funds to settle",
    "description": "Test Payin",
    "gst": false,
    "gst_amount": 0,
    "pay_by": "2025-09-29T07:46:31.300+0000",
    "sender_details": null,
    "stage": "normal_stage"
    }

2. Generate Hash via SHA256 Tool​

Sha 256 tool

  1. Visit this website (example testing).
  2. Paste the Raw Body JSON into the Input box.
  3. Enable HMAC option.
  4. Enter your Webhook Secret Key in the Key field.
  5. Ensure:
    • Input Encoding: UTF-8
    • Output Encoding: Hex (Lower Case)
  6. Copy the generated hash from the Output box.

3. Compare with Request Header​

  • In the webhook request headers, locate the header:

    http-webhook-signature: ff456ed178c487a2fd323043315320f8ec0908327a1b76f1ad54d9f81a000f9d
  • Compare the generated hash (from SHA256 tool) with the value in http-webhook-signature.

βœ… If they match β†’ Signature is valid.

❌ If they differ β†’ The request may be tampered with or key mismatch.


Example​

  • Generated HMAC (tool):

    ff456ed178c487a2fd323043315320f8ec0908327a1b76f1ad54d9f81a000f9d
  • Webhook Header:

    http-webhook-signature: ff456ed178c487a2fd323043315320f8ec0908327a1b76f1ad54d9f81a000f9d
  • βœ… Match β†’ Valid Request.

Security Best Practices​

  • Keep your Webhook Secret Key secure and never expose it publicly.
  • Always verify the signature before processing the webhook payload.