Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

webhook-hmac-verifier

Go library for webhook HMAC verification. Constant-time, framework-agnostic, zero dependencies.

Inbound webhooks from financial providers are signed so you can prove a request really came from the provider and was not tampered with or replayed. This library does that verification for the signature schemes used by Stripe, QuickBooks Online, and Bill.com webhook receivers. You hand it the raw request body plus the relevant header values, and it tells you whether the signature is authentic and fresh.

It compares signatures in constant time, rejects requests whose timestamp falls outside a configurable replay window, and returns typed errors so you can map each failure mode to the right HTTP status. It works with any HTTP stack: net/http, Gin, Echo, Fiber, Chi, or a Lambda handler.

Install

go get github.com/maxed-oss/webhook-hmac-verifier

Requires Go 1.22 or newer. No external dependencies.

Usage

Import the package as whverify.

Stripe scheme (timestamped, signed t.body)

The signature header has the form t=<unix>,v1=<hex>. The signed payload is <timestamp>.<body>. Multiple v1 values are accepted to support secret rotation. The timestamp must be within tolerance of now; pass 0 to use the 5-minute default.

import whverify "github.com/maxed-oss/webhook-hmac-verifier"

func handler(w http.ResponseWriter, r *http.Request) {
    body, _ := io.ReadAll(r.Body)
    sig := r.Header.Get("Stripe-Signature")

    err := whverify.VerifyStripe([]byte(signingSecret), body, sig, 5*time.Minute)
    switch {
    case err == nil:
        // authentic and fresh, process the event
    case errors.Is(err, whverify.ErrTimestampTooOld):
        http.Error(w, "stale", http.StatusBadRequest)
    case errors.Is(err, whverify.ErrSignatureMismatch):
        http.Error(w, "unauthorized", http.StatusUnauthorized)
    default:
        http.Error(w, "bad request", http.StatusBadRequest)
    }
}

Hex HMAC scheme (bare hex digest in one header)

For providers that send a hex-encoded SHA-256 HMAC of the raw body, such as QuickBooks Online's intuit-signature header. Pass a prefix like "sha256=" if the header carries one, or "" if it is a bare digest.

sig := r.Header.Get("intuit-signature")
err := whverify.VerifyHexHMAC([]byte(verifierToken), body, sig, "")

Base64 HMAC scheme (base64 digest in one header)

For providers that send a base64-encoded SHA-256 HMAC of the raw body, including QuickBooks Online's base64 intuit-signature value and Bill.com webhook receivers. Standard and URL-safe base64 are both accepted, with or without padding.

sig := r.Header.Get("X-Signature")
err := whverify.VerifyBase64HMAC([]byte(webhookSecret), body, sig, "")

The format it speaks

  • HMAC algorithm: SHA-256.
  • Signed payload for the Stripe scheme: <timestamp>.<raw_body>.
  • Signed payload for the hex and base64 schemes: the raw request body, exactly as received. Always verify against the raw bytes, before any JSON decoding or re-encoding, or the HMAC will not match.
  • Comparison: constant-time (crypto/hmac.Equal).
  • Replay window: absolute difference between the request timestamp and now must be within tolerance, in both directions. Future-dated requests are rejected too.

Errors

All verifiers return one of these typed errors, matchable with errors.Is:

Error Meaning
ErrEmptySecret No signing secret was supplied.
ErrNoSignature The signature header was empty or absent.
ErrMalformedSignature The header could not be parsed or decoded.
ErrSignatureMismatch The computed HMAC did not match.
ErrTimestampTooOld The request timestamp fell outside tolerance.

Test

go vet ./...
go test ./...

Agent interface

For AI agents and automation: these schemes are exposed as the verify_webhook_hmac tool in maxed-mcp, which mirrors this library (constant-time compare; stripe, hex, and base64 schemes; timestamp tolerance). See AGENT.md and llms.txt for the tool mapping.

License

MIT. See LICENSE.

About

Go library for webhook HMAC signature verification (Stripe, QuickBooks Online, Bill.com schemes). Constant-time, framework-agnostic, zero dependencies.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages