Validate webhooks

You can use your secret token to secure webhooks with a signature and validate them.

ClaimsSnap and AgentSnap use an HMAC hex digest with the SHA-256 algorithm. It is generated using your webhook subscription's secret and the payload contents. Configure a secret on the subscription to receive signed deliveries.

📘

Be careful

The signing input is JSON.stringify(payload, undefined, 2): the parsed JSON payload serialized with two-space indentation. Do not hash the raw HTTP body or sort/rearrange its keys; a different serialization produces a different signature.

The header with signature value is named x-snapr-signature-256.

Example

import { createHmac, timingSafeEqual } from 'node:crypto';

function verifyWebhook(body: unknown, signature: string | undefined, secret: string): boolean {
  if (!signature || !/^[a-f0-9]{64}$/i.test(signature)) return false;
  const serialized = JSON.stringify(body, undefined, 2);
  if (serialized === undefined) return false;

  const expected = createHmac('sha256', secret).update(serialized).digest();
  const received = Buffer.from(signature, 'hex');
  return received.length === expected.length && timingSafeEqual(received, expected);
}

// In your request handler, after parsing the JSON body:
const isValid = verifyWebhook(request.body, request.header('x-snapr-signature-256'), WEBHOOK_SECRET);

Reject the request without processing its payload if isValid is false. Signatures authenticate the payload but do not prevent replay; handle duplicate deliveries safely as described in the webhook glossary.


Did this page help you?