Skip to main content
What you need to do this:
  • The secret generated when first creating the webhook
  • The signature in the header daylight-signature
  • The string of the body included in the request

Example verification function

import crypto from 'crypto';

export function verifyDaylightWebhookSignature({
  headerSignature,
  body,
  secret,
}: {
  headerSignature: string | null | undefined;
  body: string;
  secret: string;
}) {
  //Step 1: Extract the timestamp and signatures from the header
  // (the signature var in this case)
  const sigSplit = (headerSignature || '').split(',') || [];

  let timestamp: string | undefined = undefined;
  let signature: string | undefined = undefined;
  for (const element of sigSplit) {
    const [key, value] = element.split('=');
    if (key === 't') {
      timestamp = value;
    } else if (key === 'v1') {
      signature = value;
    }
  }

  if (!signature || !timestamp) {
    throw new Error(`Missing timestamp or signature in ${signature}`);
  }

  // Step 2: Prepare the signed_payload string
  const toSign = `${timestamp}.${body}`;

  //Step 3: Determine the expected signature
  const hash = crypto
    .createHmac('sha256', secret)
    .update(toSign)
      // use base64url instead of base64 to escape equal signs
      // a header ending with an = is invalid!
    .digest('base64url');

  if (hash !== signature) {
    throw new Error(`Incorrect signature value in ${signature}`);
  }

  return true;
}