Help us shape the future of Go! Take the 2026 Go Developer Survey

webhook

package
v0.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package webhook verifies bounded original webhook bytes before typed decoding. Verified identities are bound to a configured provider/account and are not a replacement for current domain authorization or durable idempotency.

Index

Constants

View Source
const (
	SHA256 HMACAlgorithm = "sha256"
	SHA512 HMACAlgorithm = "sha512"
	// SHA1 exists only for legacy providers; prefer SHA256 when offered.
	SHA1 HMACAlgorithm = "sha1"

	Hex    SignatureEncoding = "hex"
	Base64 SignatureEncoding = "base64"
)

Variables

View Source
var (
	InvalidSignature = safeerror.New("webhook signature or freshness is invalid")
	BodyTooLarge     = safeerror.New("webhook body exceeds its configured limit")
)

Functions

This section is empty.

Types

type Config

type Config struct {
	Provider     Provider
	Protocol     Protocol
	MaxBodyBytes int64
	Tolerance    time.Duration
	// HMAC configures the HMAC protocol and must be zero for the others.
	HMAC HMACScheme
}

Config selects the provider, signature protocol and verification bounds.

func DefaultConfig

func DefaultConfig(provider Provider, protocol Protocol) Config

DefaultConfig returns verification settings with a one-megabyte body limit and five-minute timestamp tolerance.

func GitHubConfig

func GitHubConfig(provider Provider) Config

GitHubConfig verifies X-Hub-Signature-256 (hex HMAC-SHA256 of the body). GitHub signs no timestamp or ID: the delivery ID is the body digest and X-GitHub-Delivery is unverified metadata.

func ShopifyConfig

func ShopifyConfig(provider Provider) Config

ShopifyConfig verifies X-Shopify-Hmac-Sha256 (base64 HMAC-SHA256 of the body). Shopify signs no timestamp or ID: the delivery ID is the body digest and X-Shopify-Webhook-Id is unverified metadata.

func SlackConfig

func SlackConfig(provider Provider) Config

SlackConfig verifies X-Slack-Signature ("v0=" hex HMAC-SHA256 of "v0:{X-Slack-Request-Timestamp}:{body}") with freshness checking. Slack sends no delivery header; the delivery ID digests the signed timestamp and body.

func (Config) Validate

func (c Config) Validate() error

Validate checks the provider, protocol, body and timestamp bounds, and protocol-specific HMAC settings.

type Delivery

type Delivery[A any] struct {
	// contains filtered or unexported fields
}

Delivery contains only signature-authenticated metadata and the configured account. Its unexported proof prevents construction of a verified zero value.

func (Delivery[A]) Account

func (d Delivery[A]) Account() A

Account returns the verifier's account, or its zero value for an uninitialized delivery.

func (Delivery[A]) Format

func (Delivery[A]) Format(state fmt.State, _ rune)

Format writes a delivery label without exposing verified data.

func (Delivery[A]) ID

func (d Delivery[A]) ID() DeliveryID

ID returns the verified delivery identifier.

func (Delivery[A]) Provider

func (d Delivery[A]) Provider() Provider

Provider returns the verifier's provider, or an empty provider for an uninitialized delivery.

func (Delivery[A]) Timestamp

func (d Delivery[A]) Timestamp() time.Time

Timestamp returns the verified delivery timestamp.

func (Delivery[A]) UnverifiedProviderID

func (d Delivery[A]) UnverifiedProviderID() (string, bool)

UnverifiedProviderID returns the provider's delivery header of an HMAC scheme (for example X-GitHub-Delivery). The signature does not cover it, so it is diagnostic metadata only: never use it for deduplication or authorization. ID is the authenticated identity.

type DeliveryID

type DeliveryID string

DeliveryID identifies a webhook delivery within its provider.

type HMACAlgorithm

type HMACAlgorithm string

HMACAlgorithm selects the HMAC digest algorithm.

type HMACScheme

type HMACScheme struct {
	SignatureHeader string
	Prefix          string
	Algorithm       HMACAlgorithm
	Encoding        SignatureEncoding
	TimestampHeader string
	PayloadPrefix   string
	Separator       string
	DeliveryHeader  string
}

HMACScheme describes a provider's HMAC signature. SignatureHeader carries one signature, optionally after Prefix (for example "sha256="). The signed content is the exact body, or, with TimestampHeader, PayloadPrefix + timestamp + Separator + body (Slack signs "v0:" + timestamp + ":" + body). A timestamp is Unix seconds checked against Config.Tolerance; without one no freshness check is possible. The delivery ID is always "sha256-" + the digest of the verified signed content, because these schemes sign no ID: durable idempotency then rejects replays of identical signed content, but a provider that legitimately resends an identical body without a signed timestamp is indistinguishable from a replay. DeliveryHeader names an optional provider delivery header exposed only as Delivery.UnverifiedProviderID. Endpoint secrets are used verbatim as HMAC keys.

type Protocol

type Protocol string

Protocol selects the incoming webhook signature format.

const (
	Standard Protocol = "standard_webhooks"
	Stripe   Protocol = "stripe"
	// HMAC is a configurable single-header HMAC signature (Config.HMAC); see
	// the GitHub, Shopify and Slack presets.
	HMAC Protocol = "hmac"
)

type Provider

type Provider string

Provider identifies an incoming webhook source.

type SignatureEncoding

type SignatureEncoding string

SignatureEncoding selects the textual representation of a signature digest.

type Verifier

type Verifier[A any] struct {
	// contains filtered or unexported fields
}

Verifier retains immutable configuration and a bounded rotation keyring. Use separate endpoint secrets for each account; account comes from trusted setup, never from an unsigned header. Account values should be immutable domain IDs.

func New

func New[A any](config Config, account A, keys []secret.String, source clock.Clock) (*Verifier[A], error)

New supports Standard Webhooks whsec_ HMAC keys and whpk_ Ed25519 public keys, Stripe endpoint secrets, or HMAC-protocol secrets (both used verbatim). No keys are loaded from requests.

func (Verifier[A]) Format

func (Verifier[A]) Format(state fmt.State, _ rune)

Format writes a verifier label without exposing keys or account data.

func (*Verifier[A]) FromContext

func (v *Verifier[A]) FromContext(ctx context.Context) (Delivery[A], bool)

FromContext returns typed metadata attached by this exact verifier. It is not a credential and does not authorize future requests or application resources.

func (*Verifier[A]) Validate

func (v *Verifier[A]) Validate() error

Validate checks that keys and a clock are configured and validates verification settings.

func (*Verifier[A]) Verify

func (v *Verifier[A]) Verify(ctx context.Context, headers http.Header, body []byte) (Delivery[A], error)

Verify authenticates the original bytes. It intentionally permits a valid duplicate within the freshness window; use existing idempotency for effects.

func (*Verifier[A]) VerifyRequest

func (v *Verifier[A]) VerifyRequest(r *http.Request) (Delivery[A], error)

VerifyRequest reads at most MaxBodyBytes+1 bytes, closes the body it reads and restores the exact signed bytes after successful verification for typed decoding. Place it before middleware that transforms/decompresses the body.

func (*Verifier[A]) WithDelivery

func (v *Verifier[A]) WithDelivery(ctx context.Context, d Delivery[A]) (context.Context, error)

WithDelivery attaches a delivery from this verifier to a non-nil context, rejecting foreign or uninitialized deliveries.

Directories

Path Synopsis
Package outbound delivers signed webhooks to registered endpoints.
Package outbound delivers signed webhooks to registered endpoints.
command
Package command supplies outbound webhook delivery inspection and replay.
Package command supplies outbound webhook delivery inspection and replay.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL