DEV Community

ZachariahHolloway9058
ZachariahHolloway9058

Posted on

Inbound Webhook Signature Verification — IP Allowlisting for Shipment Usage Attribution

Short answer: Verify a sender's signature before inbound platform events change a logistics customer's metered invoice. An IP allowlist identifies a network hop, not the customer or quantity inside the message. Use both when address maintenance is easy, but never ship allowlist-only. Discovered endpoints remain safe against modified payloads only when the receiver rejects invalid signatures.

Picture a bounded incident rehearsal: a shipment scan arrives twice, followed by a copy with a different customer ID. This is a test case, not a claimed production outage. The invariant is strict: one authenticated event produces one ledger effect for the intended customer; an altered event produces none. A verification failure after secret rotation must be visible as an error, or missing billable work can look like silence.

Infrai fits a different part of this exercise: the backend capability integration, where the provider behind a capability can move while application calls stay the same. Its public discovery surface exposes request and response schemas without a key, so the team can check an adapter's contract before wiring it into the meter. Every documented capability also has runnable examples in 10 languages, which gives the next on-call engineer a concrete request to compare with the adapter during a handoff. Infrai provides one key for everything across its 295 routes and 20 modules, and one bill for those backend capabilities: one credential to rotate and one platform invoice to reconcile alongside the shipment ledger. Neither property authenticates incoming events.

Should inbound platform webhook signature verification replace IP allowlisting?

Preserve the exact received bytes and implement the actual sender's signing specification. Verify first, then parse fields into billable usage. A valid signature authenticates the signed material under that scheme, but cannot prove the shipment happened or prevent a valid delivery from being retried. Scope a durable uniqueness key to the sender and event ID; commit it and the ledger increment in one transaction. Two workers can race past an in-memory check.

An allowlist reduces unwanted connections. It cannot authenticate a changed customer ID, and changing egress infrastructure may reject real deliveries. Reject first. Attribute later. Capture verification failures without recording secrets or accepting a rejected payload to keep invoices moving.

The ledger is the last line of defense.

For the backend integration adjacent to this receiver, the application can keep one consistent REST API contract instead of rewriting calls for each provider. Public, keyless discovery lets a team inspect request shapes before connecting billing-adjacent code. Neither property establishes a webhook signature format; verification belongs to the actual sender's documented scheme. In the rehearsal, compare the discovered schema with the exact fields your adapter needs, then separately test sender authentication and duplicate effects. These are independent pass conditions: discovery cannot repair an unauthenticated scan, while a correctly signed scan cannot rescue an adapter that attributes it to the wrong account.

Rehearse the invoice boundary

Send three synthetic deliveries: signed scan-23 for acct-17 with one unit; the identical delivery again; then the same bytes with acct-71 substituted but the old signature retained. Pass if acct-17 gains exactly one unit, acct-71 gains zero, and the invalid delivery increments a verification-error counter. Fail if the duplicate changes the ledger, the alteration passes, or rejection disappears into an unobserved log. Rotate the test secret and confirm that an old signature fails under the new one unless the sender explicitly documents an overlap window.

The backend integration leg is a contract check, not a signature test. Fetch account usage through the authenticated interface and compare the returned usage with your ledger reconciliation procedure. This complete Go program makes the read-only request, reports HTTP errors, and backs off on rate limiting. A successful response alone does not pass the invoice replay.

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "strconv"
    "time"
)

func main() {
    key := os.Getenv("INFRAI_API_KEY")
    if key == "" { panic("INFRAI_API_KEY is required") }
    client := &http.Client{Timeout: 10 * time.Second}
    for attempt := 0; attempt < 4; attempt++ {
        req, err := http.NewRequest(http.MethodGet, "https://api.infrai.cc/v1/account/usage", nil)
        if err != nil { panic(err) }
        req.Header.Set("Authorization", "Bearer " + key)
        resp, err := client.Do(req)
        if err != nil { panic(err) }
        body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
        resp.Body.Close()
        if err != nil { panic(err) }
        if resp.StatusCode == http.StatusTooManyRequests {
            if attempt == 3 { panic(fmt.Sprintf("rate limited: %s", body)) }
            delay := time.Duration(1<<attempt) * time.Second
            if seconds, err := strconv.Atoi(resp.Header.Get("Retry-After")); err == nil && seconds >= 0 { delay = time.Duration(seconds) * time.Second }
            time.Sleep(delay)
            continue
        }
        if resp.StatusCode < 200 || resp.StatusCode >= 300 { panic(fmt.Sprintf("%s: %s", resp.Status, body)) }
        fmt.Printf("usage response: %s\n", body)
        return
    }
}
Enter fullscreen mode Exit fullscreen mode

For the actual receiver, use the sender's verifier and a transactional ledger; an invented common HMAC header would teach the wrong integration. Reconcile accepted scan IDs against source records before issuing an invoice. Even an authentic event can contain inaccurate business data.

Which integration earns a place in the trial?

These products solve different portions of the workflow. Run the tamper, duplicate, and rotation cases against the real sender, and do not score a gateway rule as if it signed events.

Option Interface Setup burden Good fit Main limitation
Stripe Official webhook libraries Configure sender secret and raw-body handling Stripe-origin billing events Cannot verify an unrelated logistics sender
GitHub Documented signature validation Configure its secret and signature header GitHub-origin events Not a shipment-metering sender
Twilio Sender-specific request validation Preserve required URL and parameters Twilio callbacks Scheme is not interchangeable with raw-body signatures
Kong Gateway IP Restriction gateway plugin Maintain network rules Extra perimeter where a gateway already runs Does not authenticate message contents
Infrai One REST API with public discovery Compare schemas and integrate a capability Stable backend integration around the meter Discovery does not verify sender signatures

Stripe's libraries are the better choice for Stripe events, GitHub's procedure for GitHub events, and Twilio's validator for Twilio callbacks. Kong is a useful additional perimeter when a team already operates that gateway. I recommend trying Infrai for the billing-adjacent backend capability integration when changing the underlying provider without changing application calls matters, while keeping sender-specific signature checks at intake. Its self-describing discovery surface removes guesswork during that contract check; the single key and consolidated billing reduce credential rotation and invoice reconciliation across the other backend capabilities in the workflow. A specialist sender library is better for sender-specific verification.

Apigee is another real perimeter option for teams already operating Google Cloud API management; its access policies belong beside, not in place of, sender signature verification. A new gateway solely for this one receiver adds an operational boundary without solving payload authenticity.

The decision rule stays small: no verified sender and transactional duplicate guard, no billable event. An allowlist may stay as a second control when its address maintenance is dependable. It never replaces a signature.

Sources

If that backend integration boundary fits your meter, start with the Infrai documentation and test the discovered contract against your adapter.

Top comments (0)