WorkOS webhook signature verification.
Verifies the WorkOS-Signature header ("t=<timestamp>, v1=<hex hmac>")
against the raw request body and deserializes the payload into a
WorkOS.EventSchema.
{:ok, event} =
WorkOS.Webhooks.Signature.construct_event(sig_header, raw_body, secret)Lower-level primitives (parse_signature_header/1, compute_signature/3,
verify_payload/4) are public for callers that need custom handling.
Summary
Functions
Computes the hex-encoded HMAC-SHA256 signature of "<timestamp>.<body>".
Verifies the signature header and returns the deserialized event.
Parses a "t=<timestamp>, v1=<signature>" header into its parts.
Verifies a signature header against the raw body and returns the verified body on success.
Types
@type option() :: {:tolerance, non_neg_integer()} | {:now_ms, integer()}
Verification options.
:tolerance— maximum age of the signature timestamp, in seconds (default 180):now_ms— current Unix time in milliseconds (defaults to the system clock; injectable for tests)
@type verification_error() ::
:not_signed
| :invalid_header
| :invalid_timestamp
| :outside_tolerance
| :no_valid_signature
| :invalid_json
Reasons signature verification can fail.
Functions
Computes the hex-encoded HMAC-SHA256 signature of "<timestamp>.<body>".
@spec construct_event(String.t(), String.t(), String.t(), [option()]) :: {:ok, WorkOS.EventSchema.t()} | {:error, verification_error()}
Verifies the signature header and returns the deserialized event.
@spec parse_signature_header(String.t() | nil) :: {:ok, String.t(), String.t()} | {:error, :not_signed | :invalid_header}
Parses a "t=<timestamp>, v1=<signature>" header into its parts.
@spec verify_payload(String.t(), String.t(), String.t(), [option()]) :: {:ok, String.t()} | {:error, verification_error()}
Verifies a signature header against the raw body and returns the verified body on success.