Webhooks

Verify signatures

Prove that a delivery really comes from Whazzup.

Verify

  1. Read the raw request body and the X-Whazzup-Signature header.
  2. Check the timestamp t is recent (for example within 5 minutes) to block replays.
  3. Compute HMAC-SHA256 of t + "." + body with your secret.
  4. Compare with v1 using a timing-safe comparison. Reject mismatches with 401.

Examples

Node.js
import { createHmac, timingSafeEqual } from "crypto";

function isValid(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = createHmac("sha256", secret)
    .update(`${parts.t}.${rawBody}`)
    .digest("hex");
  return timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}
Python
import hmac, hashlib, time

def is_valid(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > 300:
        return False
    expected = hmac.new(
        secret.encode(),
        parts["t"].encode() + b"." + raw_body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(parts["v1"], expected)