Coffrify.Webhook.Verification (Coffrify v0.9.0)

View Source

Verify Coffrify webhook signatures.

Coffrify follows Standard Webhooks v2:

  • webhook-id — opaque event id
  • webhook-timestamp — Unix seconds
  • webhook-signaturev1,<base64(hmac-sha256(id.ts.body))>

Secrets prefixed with whsec_<base64url> have their key decoded; raw string secrets are used as-is.

Example

case Coffrify.Webhook.Verification.verify(secret, raw_body, headers) do
  {:ok, event} ->
    # event is the decoded JSON map (`"type"`, `"data"`, etc.)
    :ok

  {:error, :expired} -> :stale
  {:error, :mismatch} -> :tampered
  {:error, reason} -> reason
end

Summary

Types

event()

@type event() :: %{required(String.t()) => term()}

header_source()

@type header_source() ::
  %{optional(String.t()) => String.t() | [String.t()]}
  | [{String.t(), String.t()}]
  | (String.t() -> String.t() | nil)

reason()

@type reason() :: :malformed | :invalid_timestamp | :expired | :mismatch

secret()

@type secret() :: String.t() | [String.t()]

Functions

verify(secret, body, headers, opts \\ [])

@spec verify(secret(), binary(), header_source(), keyword()) ::
  {:ok, event()} | {:error, reason()}

Verify a webhook delivery.

body MUST be the raw bytes received on the wire — do not re-serialize. Options:

  • :tolerance_seconds — accepted clock skew (default 300).