Appearance
Signature Verification
Every webhook delivery includes an x-k42-signature header containing a hex-encoded HMAC-SHA256 signature. You should verify this signature to ensure the payload was sent by K42 and has not been tampered with.
How the Signature Is Computed
The signed message is the concatenation of your callback_url and the raw JSON request body (as a string):
message = callback_url + bodyThe HMAC-SHA256 is computed using your webhook secret as the key, and the result is hex-encoded.
Verifying in Your Handler
javascript
const crypto = require("crypto");
function verifyWebhook(secret, callback_url, raw_body, signature_header) {
const message = callback_url + raw_body;
const expected = crypto
.createHmac("sha256", secret)
.update(message)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(signature_header, "hex")
);
}
// In your request handler:
const signature = req.headers["x-k42-signature"];
const is_valid = verifyWebhook(
WEBHOOK_SECRET,
"https://your-service.com/webhooks/k42",
raw_body,
signature
);
if (!is_valid) {
return res.status(401).send("Invalid signature");
}Important Notes
- Use constant-time comparison (e.g.
crypto.timingSafeEqual) to prevent timing attacks. - The
callback_urlused in verification must match exactly what you registered when creating the webhook. - The
raw_bodymust be the raw request body bytes as a string - do not parse and re-serialize the JSON, as whitespace differences will cause verification to fail. - The signature is hex-encoded (lowercase), not base64.