iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
To secure a license-fulfillment webhook, verify its signature against the exact request bytes before parsing the payload, enforce freshness if the provider signs a timestamp, persistently deduplicate authenticated event IDs, and make license issuance idempotent. A valid signature proves the request was created by someone with the shared secret and was not altered; it does not, by itself, stop an attacker or intermediary from resending a captured valid request.
Process the request in a secure order
Treat webhook handling as an authentication step followed by a durable business workflow. Do not let unverified payload fields trigger license creation, activation, suspension, or renewal.
- Constrain the endpoint. Accept only the HTTP method your integration requires, set a request-size limit appropriate to the provider’s events, and serve the endpoint over HTTPS. Verify the provider’s current delivery requirements rather than assuming all senders use the same method, headers, or limits.
- Capture the original request. Retain the exact body bytes and the relevant headers before JSON parsing or other transformation. Signature checks may fail if middleware parses and reserializes JSON, changes character encoding, or otherwise alters signed bytes. Check that proxies and load balancers preserve the signed body.
- Authenticate with the configured provider’s verifier. Select the algorithm, header format, and secret for the sender configured on that endpoint. Validate the signature header’s syntax, calculate the provider-specified signature over the required data, and compare it in constant time. Reject missing or invalid signatures before using payload contents for business logic.
- Check freshness when the signed protocol supports it. If the provider includes a timestamp in the signed material, validate its age against that provider’s documented tolerance. A timestamp narrows the time window in which a captured request can be replayed; it does not prevent duplicate delivery within that window.
- Claim the authenticated event ID durably and atomically. Persist a stable provider event or delivery identifier before starting fulfillment. If that identifier has already been claimed or processed, do not repeat the business effect.
- Run fulfillment idempotently. Queue or execute the license operation so that retries, concurrent deliveries, and recovery after a partial failure cannot create a second grant for the same purchase or entitlement.
- Acknowledge and monitor according to the provider’s rules. Meet the sender’s response deadline, track outcomes by event identifier, and provide a safe recovery path for redelivery. Do not log signing secrets or full sensitive payloads.
Verify the signature over the exact bytes
A webhook signature is meaningful only when checked against the data the provider actually signed. Keep the raw body available at the point where the verifier runs; parsing JSON first and then serializing it again can change whitespace, ordering, escaping, or encoding. Even if the resulting JSON represents the same values, its bytes may differ.
GitHub example: HMAC-SHA256
GitHub documents HMAC-SHA256 validation using the configured webhook secret and the X-Hub-Signature-256 header. Its guidance calls for a constant-time comparison and says, “Never use a plain == operator.” See GitHub’s webhook validation documentation. Do not substitute GitHub’s legacy SHA-1 header in a new implementation.
This example is specific to GitHub’s documented format. Other providers may sign different bytes, use different algorithms or headers, or define canonicalization rules. Implement the sender’s exact protocol; do not assume that the GitHub procedure is universal.
What a successful HMAC check means
HMAC verification establishes that the received signed content matches a MAC made with the shared secret, assuming that secret remains protected. It does not encrypt the payload, establish that the event is fresh, or prevent a recipient from accepting the same valid request twice. Signature verification is necessary, but replay protection and idempotent processing are separate controls.
Rank #2
Limit replay and duplicate processing
Replay protection needs to address both captured requests and ordinary provider retries. GitHub describes a replay attack as an intercepted webhook delivery being sent again. Duplicate deliveries also occur as part of normal webhook operation, so a robust receiver must be safe even when no attacker is involved. OWASP’s webhook security guidance discusses timestamps and event identifiers in a document currently located in its draft cheat sheets; treat its recommendations as draft guidance, not a final standard.
Validate a signed timestamp when the provider supplies one
Only apply timestamp checks when the sender’s protocol defines a timestamp covered by the signature. Compare it with a trusted receiver clock and reject deliveries outside the provider’s documented tolerance. OWASP’s draft gives a ±5-minute window as an example, not a universal requirement; use the actual provider’s rules rather than copying that value blindly. A valid timestamp still allows repeat requests during the accepted window, so it cannot replace event-ID deduplication.
Rank #3
Deduplicate stable event or delivery IDs
After the signature is valid, atomically record the provider’s stable event or delivery ID in durable storage. The atomic claim matters: a separate “check whether it exists” followed by “insert if absent” can let two concurrent deliveries both pass the check. If an ID is already recorded as handled or in progress, return the provider-appropriate success response without applying fulfillment again.
For GitHub, a requested redelivery retains its original X-GitHub-Delivery value, making that delivery identifier useful for recognizing the redelivery. This behavior is GitHub-specific; confirm the identifier and redelivery semantics for any other sender in its documentation. See GitHub’s webhook best practices.
Rank #4
Make license effects idempotent too
Event deduplication protects against processing the same event ID twice, but the business operation also needs a stable idempotency key. For example, associate a license grant with the underlying order or entitlement so that a retry cannot create a second grant under a different delivery attempt. This is an application of duplicate-processing guidance to license fulfillment: the required key and uniqueness rule depend on the provider’s event and your licensing model.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsPersist enough workflow state to resume safely after a crash between claiming an event and completing fulfillment. Keep the event record and license operation coordinated so that concurrent requests cannot both create a grant, and define how an in-progress event is recovered rather than treating every retry as a new purchase.
Best Value
Separate fast acknowledgment from fulfillment
Webhook senders commonly retry when a receiver times out or returns an error. If fulfillment can take longer than the sender’s response window, authenticate and durably enqueue the work, then acknowledge it according to the provider’s requirements. The worker can issue or update the license independently, with idempotency and observable state to handle retries and partial failures.
For GitHub specifically, the receiver should return a 2XX response within 10 seconds; GitHub suggests asynchronous processing when needed. That deadline is GitHub’s delivery rule, not a general webhook timeout. Check the actual sender’s current acknowledgment deadline and retry policy before deciding how much work to do in the request handler.
Protect secrets, transport, and operational records
- Use a high-entropy signing secret. GitHub recommends a high-entropy secret stored securely. Keep it out of source code, client-side applications, error messages, and logs.
- Use HTTPS and verify TLS. GitHub recommends HTTPS and SSL verification for webhook delivery. Do not disable certificate checks to work around a transport problem.
- Plan secret changes safely. Store secrets in an access-controlled secret store and follow the provider’s supported rotation process. During a coordinated rotation, ensure sender and receiver configurations agree so legitimate deliveries do not fail.
- Log outcomes, not credentials or payload dumps. Record identifiers, verification results, processing status, and enough diagnostic context to investigate failures. Avoid logging the signing secret or full payloads that may contain personal or commercial information.
Check these details for every provider
Before enabling a new license-fulfillment integration, confirm each item in that provider’s current official documentation. The available GitHub and OWASP guidance does not establish signature formats, timestamp rules, or delivery behavior for other vendors.
Quick Recap
- Which exact bytes or canonical representation are signed?
- Which signature algorithm and header format are required, and how should malformed or missing signatures be handled?
- Is a timestamp included in the signed material, and what freshness tolerance does the provider specify?
- What stable event or delivery ID is available, and does a redelivery retain it?
- What are the acknowledgment deadline and retry behavior?
- How should the secret be stored and rotated, and does the provider supply an SDK with raw-body requirements?
Common implementation failures
- Parsing before verification: verify the original bytes before trusting or transforming the payload.
- Using an ordinary string comparison: use a constant-time comparison method supported by the language or cryptographic library.
- Treating a valid signature as replay protection: add timestamp validation when the signed protocol supports it and persistently deduplicate event IDs.
- Deduplicating only in memory: use durable storage so restarts do not erase the receiver’s history.
- Checking then inserting without an atomic constraint: make the event claim safe under concurrent deliveries.
- Making only the webhook handler idempotent: enforce uniqueness in the license-fulfillment operation as well, so recovery and retries cannot create duplicate grants.
- Assuming provider rules match: verify each sender’s headers, signature inputs, timestamp policy, delivery IDs, and deadlines independently.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

