Guides›Verifying Signatures
Verifying Signatures
DiffHook signs every webhook payload so you can verify it came from us and wasn't tampered with.
How it works
Each request includes an X-DiffHook-Signature header containing an HMAC-SHA256 signature of the raw request body, prefixed with sha256=.
X-DiffHook-Signature: sha256=abc123def456...
Your signing secret is available in App → Settings → API Keys.
Verifying in Node.js
const crypto = require('crypto')
function verifySignature(req, secret) {
const signature = req.headers['x-diffhook-signature']
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(JSON.stringify(req.body))
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
)
}
app.post('/webhook', (req, res) => {
if (!verifySignature(req, process.env.DIFFHOOK_SIGNING_SECRET)) {
return res.status(401).send('Invalid signature')
}
res.status(200).send('OK')
// process event...
})
Verifying in Python
import hmac, hashlib, json
def verify_signature(body: bytes, signature: str, secret: str) -> bool:
expected = 'sha256=' + hmac.new(
secret.encode(),
body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
Important notes
- Always use
crypto.timingSafeEqual(or equivalent) to prevent timing attacks - Compute the signature from the raw bytes of the request body, before JSON parsing
- If
X-DiffHook-Signatureis missing, reject the request
Rotating your signing secret
Rotate your signing secret in Settings at any time. After rotation, old signatures will fail — update your deployment before revoking the old secret.