Skip to main content

verifyWebhook

@rotorsoft/act-root


@rotorsoft/act-root / act-http/src/receiver / verifyWebhook

Function: verifyWebhook()

verifyWebhook(headers, body, secret, options?): VerifyResult

Defined in: libs/act-http/src/receiver/verify.ts:65

Verify an inbound webhook's signature and timestamp against the shared secret. Pair with the sender side: configure webhook({ secret }) from @rotorsoft/act-http/webhook.

Returns { ok: true } on success or { ok: false; reason } on failure. The reasons are:

  • missing-signature โ€” no X-Webhook-Signature header, value was an array, or value was empty.
  • missing-timestamp โ€” no X-Webhook-Timestamp header, value was empty, or value isn't a parseable integer.
  • stale โ€” timestamp older than maxAgeSeconds from now.
  • future โ€” timestamp more than maxAgeSeconds ahead of now.
  • bad-signature โ€” signature header didn't start with sha256=, wasn't 64 hex chars, or the recomputed HMAC didn't match (constant-time compare).

The signed payload is ${timestamp}.${body}, so body must be the raw request body bytes. Any pre-parse normalization (whitespace trimming, JSON re-stringification) would change the hash and reject every otherwise-valid request. Framework adapters in #744 will provide the raw body alongside the parsed one.

Uses Node's crypto.timingSafeEqual for the final comparison to avoid signature-equality timing attacks.

Parametersโ€‹

headersโ€‹

Record<string, string | string[] | undefined>

bodyโ€‹

string

secretโ€‹

string

options?โ€‹

VerifyOptions

Returnsโ€‹

VerifyResult