Verify webhook signatures
If you set a secret on a V2 webhook, LeadTruffle signs each delivery with HMAC SHA-256 headers:
x-leadtruffle-timestamp: Unix timestamp in secondsx-leadtruffle-signature:v1=followed by the hex HMAC SHA-256 signaturex-leadtruffle-signature-algorithm:hmac-sha256
The signature is computed over ${timestamp}.${rawRequestBody} using the webhook secret as the HMAC key. Verify the signature against the raw request body before parsing JSON.
Python verification example:
import hmac, hashlib, time
raw_body = request.get_data()
timestamp = request.headers["x-leadtruffle-timestamp"]
signature = request.headers["x-leadtruffle-signature"].removeprefix("v1=")
try:
timestamp_seconds = int(timestamp)
except ValueError:
raise Exception("invalid timestamp")
if abs(time.time() - timestamp_seconds) > 5 * 60:
raise Exception("stale webhook")
expected = hmac.new(
b"YOUR_WEBHOOK_SECRET",
timestamp.encode("utf-8") + b"." + raw_body,
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(expected, signature):
raise Exception("invalid signature")
PHP verification example:
$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_LEADTRUFFLE_TIMESTAMP'];
$signature = preg_replace('/^v1=/', '', $_SERVER['HTTP_X_LEADTRUFFLE_SIGNATURE']);
if (!ctype_digit($timestamp) || abs(time() - intval($timestamp)) > 5 * 60) {
http_response_code(401);
exit;
}
$expected = hash_hmac('sha256', $timestamp . '.' . $rawBody, 'YOUR_WEBHOOK_SECRET');
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit;
}