Signed Webhooks
Signature Format
Signature Verification
Example — TypeScript (Node.js)
import * as crypto from 'crypto';
function verifyWebhookSignature(payload: string, signatureHeader: string, secret: string) {
const [tPart, v1Part] = signatureHeader.split(',');
const timestamp = tPart.split('=')[1];
const signature = v1Part.split('=')[1];
const fiveMinutesAgo = Math.floor(Date.now() / 1000) - 300;
if (parseInt(timestamp, 10) < fiveMinutesAgo) {
throw new UnauthorizedException('Signature timestamp expired');
}
const signedPayload = `${timestamp}.${payload}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload, 'utf8')
.digest('hex');
const valid = crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature),
);
if (!valid) {
throw new UnauthorizedException('Invalid signature');
}
return valid;
}
