Signature verification
Every webhook delivery includes a signature header so you can verify the payload came from Active Reach and wasn’t tampered with.
How it works
- Active Reach computes an HMAC-SHA256 hash of the raw request body using your signing secret
- The hash is sent in the
X-Aegis-Signatureheader (the default; the header name is configurable per-webhook if your security team requires a different name) - Your server computes the same hash and compares
If the hashes match, the payload is authentic.
Verification code
import crypto from 'node:crypto';
function verifyWebhookSignature(
rawBody: string,
signature: string,
secret: string
): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your webhook handler:
const sig = req.headers['x-aegis-signature'];
const isValid = verifyWebhookSignature(req.rawBody, sig, WEBHOOK_SECRET);
if (!isValid) return res.status(401).send('Invalid signature');Important notes
- Use the raw body — parse JSON after verification, not before. Parsing and re-serializing may change whitespace/ordering.
- Use timing-safe comparison —
crypto.timingSafeEqual(Node) orhmac.compare_digest(Python). Never use===— it’s vulnerable to timing attacks. - Rotate secrets periodically — you can regenerate the signing secret in Settings → Developer → Webhooks. After rotation, payloads signed with the previous secret will fail verification.
What’s next
- Retry policy — what happens when verification fails or your endpoint is down
- Testing webhooks — verify your handler locally