Skip to main content

Signature Verification

Every webhook delivery is signed using your webhook's secret (shown in the dashboard when you create a webhook). You should always verify the signature to ensure the request is from EasyConfirm and hasn't been tampered with.

How It Works

  1. EasyConfirm computes HMAC-SHA256(secret, request_body) and sends it in the X-EasyConfirm-Signature header as sha256=<hex_digest>.
  2. Your server computes the same HMAC using your webhook secret.
  3. Compare the two values using a timing-safe comparison.

Node.js Example

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
const expectedSignature = 'sha256=' +
crypto.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}

// Express middleware
app.post('/webhooks/easyconfirm', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-easyconfirm-signature'];
const secret = process.env.WEBHOOK_SECRET;

if (!verifySignature(req.body, signature, secret)) {
return res.status(401).send('Invalid signature');
}

const event = JSON.parse(req.body);
// Process the event...

res.status(200).send('OK');
});

Python Example

import hmac
import hashlib

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = 'sha256=' + hmac.new(
secret.encode('utf-8'),
payload,
hashlib.sha256
).hexdigest()

return hmac.compare_digest(signature, expected)

PHP Example

function verifySignature(string $payload, string $signature, string $secret): bool {
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
return hash_equals($expected, $signature);
}

:::danger Never Skip Verification Always verify the X-EasyConfirm-Signature header before processing any webhook payload. This prevents attackers from sending spoofed requests to your endpoint. :::

:::tip Use Raw Body Make sure you verify the signature against the raw request body (not parsed JSON). Parsing and re-serializing JSON may change the byte representation and cause verification to fail. :::