Verify Webhook Signatures Before Your Proxy Rewrites the JSON

작성자

카테고리:

← 피드로
DEV Community · jaryn · 2026-07-19 개발(SW)

jaryn

A webhook arrives with a valid HMAC over its raw bytes. Middleware parses the JSON, changes whitespace and key order, then asks the verifier to authenticate the new serialization. The object is equivalent; the signature is not.

Preserve the signed input

import crypto from "node:crypto";
export function verify(raw, header, secret) {
  const [ts, sig] = header.split(",");
  if (Math.abs(Date.now()/1000-Number(ts)) > 300) return false;
  const expected=crypto.createHmac("sha256",secret).update(`${ts}.`).update(raw).digest("hex");
  return sig.length===expected.length && crypto.timingSafeEqual(Buffer.from(sig),Buffer.from(expected));
}

Enter fullscreen mode Exit fullscreen mode

Capture raw before JSON parsing. Bind the timestamp into the signature and store an event ID or signature digest in a five-minute replay cache. Reject a second delivery after the first succeeds.

Fixtures

Fixture Expected exact raw body accept once reordered keys reject one-byte mutation reject six-minute-old timestamp reject duplicate valid request reject as replay

Create one valid fixture with a fixed timestamp and secret, then derive every negative case from it. Never log the production signature or secret. Record only fixture ID, reason class, and request digest.

prevent: verify raw bytes before business logic
detect: reason-coded rejects and replay-cache hits
recover: rotate secret, retain sanitized evidence, replay known-good events deliberately

Enter fullscreen mode Exit fullscreen mode

This example covers HMAC webhooks, not asymmetric signatures or every provider header format. Follow the provider’s canonicalization rules. Which middleware in your stack first destroys access to the original bytes?

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다