Programming

Webhook Security: Verify Signatures and Process Duplicate Deliveries Safely

tuyenpham
October 12, 2026 schedule 5 min read
webhook security: process overview

Webhook security begins with proving that a delivery came from the expected provider and that the received bytes were not altered. It continues through durable acceptance, duplicate handling, and authorization-aware processing. A public endpoint can receive arbitrary requests even if its URL looks obscure. Use the provider-supported verification library and follow its exact signing contract. Then treat delivery as a retryable integration boundary, not as a perfectly ordered stream that always arrives once. Correct verification and correct business processing are related but separate responsibilities.

webhook security: a practical implementation workflow

Preserve the signed representation

Many providers, including Stripe, verify a signature against the raw request body. Parsing JSON and serializing it again can change whitespace or other details and break verification. Configure the webhook route so it receives the required raw bytes before a general JSON parser modifies them. Bound body size at the appropriate layer and require the expected method and content type. Provider schemes differ, so do not invent a universal signature formula. The sample uses a configured Stripe SDK instance to verify a captured fixture rather than implementing cryptography manually.

webhook security: overview
Overview

Check signatures with the right secret and policy

A webhook endpoint secret is not interchangeable with an API access key. Use the secret for the specific environment and endpoint, store it outside source control, and plan rotation using the provider guidance. Verification schemes may include a signed timestamp and freshness tolerance to constrain replay. Keep clocks accurate and follow the actual provider policy. Reject a failed verification before trusting event fields. Do not disable verification because a local test fixture fails; inspect raw-body capture, header handling, environment configuration, and the fixture generation procedure instead.

Acknowledge after durable acceptance

A successful response tells the provider that delivery was accepted under its retry contract. Returning success before an event reaches durable storage can lose the event if the process crashes. Persist an inbox record or enqueue through an appropriately durable mechanism before acknowledging. If persistence fails, respond according to the provider retry behavior rather than pretending acceptance. Keep the request handler small and move expensive work to a worker when appropriate. Ensure that queue acceptance, deduplication, and operational monitoring cover the actual failure modes of the chosen infrastructure.

Handle duplicates and order independently

webhook security: checklist
Checklist

Store verified provider event identifiers with a unique constraint and avoid repeating a completed business effect. A check in memory is insufficient across service instances. Duplicate delivery detection is not the same as deduplicating separate events that describe the same business transition. Choose the right business identity and state transition rules for your integration. Stripe does not guarantee delivery ordering, so avoid trusting arrival order or a creation timestamp as a complete sequencing mechanism. Fetch authoritative resource state or apply an explicit state model when the event history alone is insufficient.

Keep workers and replay tools safe

After verification, validate the event type and the fields your consumer needs. Map provider objects to the correct local account rather than trusting an unverified tenant identifier. Workers need bounded retries and a visible path for failures that cannot be resolved automatically. Restrict manual replay tools because replay can trigger real effects. Logs should capture event identifiers, processing state, and diagnostic codes without exposing secrets or full sensitive payloads. Test recovery after acceptance but before processing, since this boundary determines whether a restart loses or repeats work.

Code example

webhook security: workflow
Workflow

The function accepts the original Buffer or provider-supported raw representation. It throws when verification fails. A production route still needs raw-body middleware, size limits, durable acceptance, event validation, and duplicate-safe workers; this is only the signature boundary.

export function verifyFixture(stripe, rawBody, signature, endpointSecret) {
  // stripe is a configured instance of the official Stripe Node SDK.
  return stripe.webhooks.constructEvent(
    rawBody, signature, endpointSecret
  );
}

Worked example

A hypothetical billing webhook initially parses every request as JSON before verification. The team fixes route-specific raw-body handling and uses a provider test tool to generate a signed fixture. It persists accepted event identifiers before replying, then processes the event in a worker. Replaying the same delivery produces no additional entitlement change. A later event arrives before an earlier one, so the consumer consults current provider state rather than reversing access based only on arrival order. Verification protects origin; the state model protects the business outcome.

Verification checklist

  • Verify the original body with the endpoint secret.
  • Persist accepted events before sending success.
  • Test duplicate deliveries across multiple workers.
  • Recover safely from out-of-order and delayed events.
webhook security: mistakes
Mistakes

Practice task

Create signed test fixtures with the official provider SDK or CLI. Change one body byte and confirm rejection, then test a missing signature and the wrong endpoint secret. Replay a valid event twice and verify one intended state transition. Simulate queue failure and a worker restart after durable acceptance. Deliver related events in reverse order and document the reconciliation rule. Keep fixtures free of real customer data, and distinguish verification success from successful completion of downstream business processing.

Sources and related reading

Consult Stripe webhook delivery guidance; Stripe signature troubleshooting; OWASP webhook security for API contracts and implementation details. Continue with Web Security Basics and Integration Testing for related concepts.

Share Article: share

Discussion

Join the conversation

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Articles