stripe-webhook-signature-verificationlisted
Install: claude install-skill jacob-balslev/skill-graph
# Stripe Webhook Signature Verification
## Coverage
- The raw-body requirement — why `stripe.webhooks.constructEvent()` requires the unparsed `Buffer` from the request body, and how Next.js App Router routes expose it via `request.arrayBuffer()`
- HMAC-SHA256 verification — how `constructEvent(rawBody, signature, secret)` reconstructs and compares the Stripe signature internally
- Replay protection — the 300-second tolerance window Stripe checks against the `t=` timestamp embedded in the `stripe-signature` header; when to tighten it
- Environment-specific secrets — `STRIPE_WEBHOOK_SECRET` for production vs `whsec_...` from the Stripe CLI `--forward-to` session in development; why they must never be swapped
- Idempotency key pattern — recording the `event.id` in Postgres before processing so a retried delivery does not double-charge or double-fulfill
## Philosophy
A webhook that skips signature verification is an unauthenticated public endpoint that can trigger payment processing. The verification step is load-bearing security, not a convenience check. Stripe's SDK makes verification a single call, but two failure modes are common in practice: the request body gets parsed (by a body-parser middleware) before the raw bytes reach the verification call, which silently corrupts the HMAC comparison; and the wrong webhook secret is loaded from environment variables, producing a 400 that is hard to distinguish from a replay rejection. Both failures look the same to the caller — a