Skip to main content
Menu
On this page

Webhook signature verification failed

Check the raw request body, the signing secret, and the signature header before you process a webhook event.

A webhook signature covers the exact request bytes Fillo sent. Parsing the JSON and serializing it again changes those bytes, even when the object looks identical.

Verify before parsing

  1. Read the request body as raw bytes or text.
  2. Read the Fillo signature header exactly as documented by the webhook endpoint.
  3. Compute the expected HMAC with that endpoint's current signing secret.
  4. Compare the provided and expected values with a constant-time comparison.
  5. Only then parse the JSON and dispatch the event.
ts
import { createHmac, timingSafeEqual } from "node:crypto";

const expected = createHmac("sha256", process.env.FILLO_WEBHOOK_SECRET!)
  .update(rawBody)
  .digest("hex");

const providedBuffer = Buffer.from(providedSignature, "hex");
const expectedBuffer = Buffer.from(expected, "hex");
const valid = providedBuffer.length === expectedBuffer.length
  && timingSafeEqual(providedBuffer, expectedBuffer);

Use the header name and encoding shown for the live webhook configuration. Don't strip prefixes or convert encodings until you've compared them against the received value.

Common causes

  • A framework JSON body parser ran before the verifier.
  • The secret belongs to a different destination, workspace, or environment.
  • The copied secret picked up whitespace or dropped a character.
  • A reverse proxy decompressed, decoded, or otherwise changed the body.
  • Test tooling supplied a JSON object instead of the captured raw payload.

When you rotate a secret, allow for in-flight deliveries if your deployment can't change atomically. Keep both values private and remove the previous one promptly after verification.

Signature checks aren't deduplication

A valid event can be delivered again. Store the event or response identity your handler has processed and make downstream effects idempotent. Return a successful status only after the event is durably accepted — a timeout after your commit can cause Fillo to retry.

  • Webhooks: Configure endpoints, events, retries, and payload handling.
  • Delivery health and replay: Inspect terminal failures after verification is repaired.
  • Security: Keep signing secrets out of logs and client bundles.

Updated

Was this page helpful?