Verify webhooks
Every webhook is signed with your secret. Reject the request if the signature does not match.
Request
Headers
X-Ildstedet-Webhook-Signaturehex stringRequiredHMAC-SHA256 of the raw body, hex-encoded.
X-Ildstedet-Webhook-VersionstringRequiredPayload version. The same value is in the JSON field webhookVersion.
Check
- Read the raw body bytes. Do not parse JSON first and re-serialize it.
- Compute HMAC-SHA256 of those bytes with your signing secret.
- Compare the hex digest to the signature header with a timing-safe comparison.
- Parse and handle the JSON only after the comparison succeeds.
Example
import { createHmac, timingSafeEqual } from 'node:crypto'
export function verifyIldstedetWebhook(rawBody, signature, secret) {
const digest = createHmac('sha256', secret).update(rawBody).digest('hex')
const actual = Buffer.from(signature ?? '', 'utf8')
const expected = Buffer.from(digest, 'utf8')
if (actual.length !== expected.length) return false
return timingSafeEqual(actual, expected)
}The signature covers the entire raw body, including
webhookVersion. Webhooks are sent to HTTPS endpoints only.