WorkOS.Webhooks.Signature (WorkOS SDK for Elixir v3.0.1)

Copy Markdown View Source

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

Types

Verification options.

Reasons signature verification can fail.

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

option()

@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)

verification_error()

@type verification_error() ::
  :not_signed
  | :invalid_header
  | :invalid_timestamp
  | :outside_tolerance
  | :no_valid_signature
  | :invalid_json

Reasons signature verification can fail.

Functions

compute_signature(secret, timestamp, body)

@spec compute_signature(String.t(), String.t(), String.t()) :: String.t()

Computes the hex-encoded HMAC-SHA256 signature of "<timestamp>.<body>".

construct_event(sig_header, body, secret, opts \\ [])

@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.

parse_signature_header(header)

@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.

verify_payload(sig_header, body, secret, opts \\ [])

@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.