HookSniff.Webhook (hooksniff v1.1.1)

Webhook signature verification for incoming HookSniff webhooks.

Verifies HMAC-SHA256 signatures in Standard Webhooks format. Supports whsec_ prefixed secrets and replay protection (5-minute tolerance).

Usage

secret = "whsec_base64encoded..."
headers = %{
  "webhook-id" => "msg_123",
  "webhook-timestamp" => "1678900000",
  "webhook-signature" => "v1,abc123..."
}
body = ~s({"event": "order.created"})

{:ok, payload} = HookSniff.Webhook.verify(body, headers, secret)
{:error, %HookSniff.Webhook.VerificationError{}} = HookSniff.Webhook.verify(body, bad_headers, secret)

Summary

Functions

Sign a payload (for testing or server-side webhook sending).

Verify a webhook payload against its signature headers.

Functions

sign(msg_id, timestamp, payload, secret)

@spec sign(String.t(), integer(), String.t(), String.t() | binary()) :: String.t()

Sign a payload (for testing or server-side webhook sending).

Parameters

  • msg_id — The message ID
  • timestamp — Unix timestamp (integer)
  • payload — The payload string
  • secret — The signing secret

Returns

Signature string in "v1,base64hmac" format.

verify(payload, headers, secret)

@spec verify(String.t(), map(), String.t() | binary()) ::
  {:ok, term()} | {:error, HookSniff.Webhook.VerificationError.t()}

Verify a webhook payload against its signature headers.

Parameters

  • payload — The raw request body (string)
  • headers — Map with webhook-id, webhook-timestamp, webhook-signature keys (also accepts svix-id, svix-timestamp, svix-signature)
  • secret — The endpoint's signing secret (e.g., "whsec_...")

Returns

  • {:ok, parsed_payload} if verification succeeds
  • {:error, %VerificationError{}} if verification fails