SaaS webhook security: signatures, retries and idempotent handling
Secure webhook delivery and receivers with HMAC verification, HTTPS, replay-aware event handling, idempotent processing and monitored retries.
In this guide
How do you secure a SaaS webhook receiver?
A webhook sends an event to an HTTPS endpoint when something changes. Because an endpoint may be called by anyone who can reach it, verify the provider's signature before trusting or processing the payload. HMAC can authenticate a message when the sender and receiver share a secret; it does not automatically prevent duplicate delivery, replay or business-level mistakes.
Verify the signature over the original request body
Follow the provider's exact signing format and verify the signature against the raw bytes before parsing or normalising JSON. Use a vetted cryptographic library and a constant-time comparison. GitHub documents an HMAC-SHA256 signature over the payload; other providers may use different headers or formats, so never assume they are interchangeable.
Use HTTPS and keep the signing secret out of the URL
Require HTTPS with certificate verification and store each endpoint secret in managed secret storage. Do not put the secret in a query string, source code, client-side configuration or logs. Limit who can view, rotate or replace the secret and record changes without storing its value.
Validate event type, tenant and allowed actions
After signature verification, validate the expected event type, payload shape, tenant, resource and state transition. A valid signature proves the message used a shared secret; it does not prove the requested business action is allowed in the current account or still current. Recheck authorization and state before applying the change.
| Provider / event | Signature and key version | Deduplication key | Retry and ordering policy | Alert owner / test date |
|---|---|---|---|---|
How should a receiver handle retries and duplicate events?
Acknowledge quickly and process asynchronously
Verify the request, persist a small delivery record and enqueue the work before returning the provider's expected success response. Avoid slow database workflows or third-party calls in the request window. Follow the specific provider's timeout and retry behavior; GitHub, for example, recommends responding to its deliveries within ten seconds.
Make event processing idempotent
Use a stable provider delivery ID or event ID with a uniqueness constraint in your durable inbox. If the same signed delivery arrives again, acknowledge it without repeating the side effect. For business actions such as payment updates, also check the current resource state because different event IDs may describe the same underlying change.
Plan for delayed and out-of-order messages
Do not assume delivery order is business order. Compare a provider version, event timestamp or resource version where available, and fetch current provider state when a stale event could cause an incorrect transition. Make retry, dead-letter and manual replay paths visible and safe to run twice.
How do you operate webhook integrations over time?
Rotate secrets with a controlled overlap
Create a replacement secret, update the provider and monitor successful deliveries before removing the old key. If your protocol permits, verify against a short list of active key versions during the change window. Set a removal deadline; indefinite dual verification makes a retired secret useful to an attacker.
Subscribe only to needed events and monitor delivery health
Limit subscriptions to events the integration handles. Track accepted, rejected, delayed and repeatedly failing deliveries by endpoint and tenant, but redact payload secrets and personal data from telemetry. Alert on sustained failure or backlog and provide a scoped tool for authorized redelivery.
Test signature, replay and outage cases
Test invalid signatures, changed payload bytes, missing headers, repeated IDs, secret rotation, provider timeouts, receiver outages and oversized payloads. Confirm an invalid request is rejected before side effects, a retry does not duplicate work and operators can safely replay a missed event.
SaaS webhook questions
Does an HMAC signature stop webhook replay?
Not by itself. A valid signature can be copied with the signed body. Use provider timestamps or nonces when available, enforce a reasonable freshness window, and deduplicate stable delivery IDs. Check each provider's documented delivery format.
Should I parse JSON before checking the signature?
No, when the provider signs the original body. Read the raw request bytes, verify the provider's signature as documented and only then parse and validate the payload. A framework's body parser may need a raw-body route or middleware configuration.
Can I trust a webhook because it came from a known IP address?
An IP allowlist can add a network control when the provider publishes stable ranges, but it does not replace signature validation. Provider ranges can change; maintain them from the official source and keep TLS verification enabled.
Should webhook retries run the business action again?
A retry should safely complete work that did not finish, not repeat an already committed side effect. Persist a delivery ID, make the handler idempotent and reconcile the resource's current state before applying changes.
Related practical guides
Related issue guides
Sources and publication record
Draft prepared 27 September 2026; engineering, security and editorial review pending · Sources checked .
- GitHub Docs: Validating webhook deliveriesGitHub
- GitHub Docs: Best practices for using webhooksGitHub
- IETF RFC 2104: HMAC keyed-hashing for message authenticationInternet Engineering Task Force
- OWASP Cheat Sheet: Secrets ManagementOWASP Foundation
- OWASP Cheat Sheet: LoggingOWASP Foundation