Module: Rerout::Webhooks
- Defined in:
- lib/rerout/webhooks.rb
Overview
Webhook signature verification.
Rerout signs every webhook delivery with an ‘X-Rerout-Signature` header shaped as `t=unix_seconds,v1=hex_hmac_sha256`. The HMAC is computed over `“timestamp.raw_body”` with the endpoint signing secret (`whsec_…`) as the key.
Constant Summary collapse
- DEFAULT_TOLERANCE_SECONDS =
Default tolerance window in seconds between the ‘t=` timestamp and the current time. Five minutes — protects against captured-replay attacks.
300
Class Method Summary collapse
-
.verify_signature(raw_body:, signature_header:, secret:, tolerance_seconds: DEFAULT_TOLERANCE_SECONDS, now: nil) ⇒ Boolean
Verify a Rerout webhook signature.
Class Method Details
.verify_signature(raw_body:, signature_header:, secret:, tolerance_seconds: DEFAULT_TOLERANCE_SECONDS, now: nil) ⇒ Boolean
Verify a Rerout webhook signature.
Returns ‘true` only when the header parses cleanly, the timestamp is within `tolerance_seconds` of `now`, and the computed HMAC matches the supplied `v1` in constant time. Returns `false` for every failure mode —it never raises.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/rerout/webhooks.rb', line 41 def self.verify_signature(raw_body:, signature_header:, secret:, tolerance_seconds: DEFAULT_TOLERANCE_SECONDS, now: nil) return false if raw_body.nil? return false if signature_header.nil? || signature_header.to_s.empty? return false if secret.nil? || secret.to_s.empty? parsed = parse_header(signature_header.to_s) return false if parsed.nil? , v1 = parsed return false unless within_tolerance?(, tolerance_seconds, now) expected = OpenSSL::HMAC.hexdigest('SHA256', secret.to_s, "#{}.#{raw_body}") secure_compare(expected, v1) end |