Module: Helo::WebhookSignatures
- Defined in:
- lib/helo/webhook_signatures.rb
Overview
Helpers for verifying the signature on an incoming webhook request.
Defined Under Namespace
Classes: Error, MalformedHeaderError, SignatureMismatchError, TimestampSkewError, UnsupportedVersionError
Constant Summary collapse
- SUPPORTED_VERSIONS =
Signing schemes this SDK can verify. The signature header may carry several versions at once (t=...,v1=...,v2=...) so that a new scheme can be rolled out while receivers upgrade; verification uses the newest version present that appears in this list, and ignores the rest.
[1].freeze
- TIMESTAMP_VALUE_REGEX =
/\A\d+\z/- SIGNATURE_KEY_REGEX =
/\Av(\d+)\z/- HEX_SIGNATURE_REGEX =
/\A[a-f0-9]+\z/- MAX_TIMESTAMP_SKEW_SECONDS =
5 minutes
300
Class Method Summary collapse
-
.generate(payload, key, timestamp) ⇒ String
Compute the hex-encoded HMAC-SHA256 signature for a webhook payload, using the v1 signing scheme.
-
.valid?(signature_header, request_body, signing_key) ⇒ Boolean
Verify a webhook signature header, returning false instead of raising.
-
.verify!(signature_header, request_body, signing_key) ⇒ true
Verify a webhook signature header against the raw request body.
Class Method Details
.generate(payload, key, timestamp) ⇒ String
Compute the hex-encoded HMAC-SHA256 signature for a webhook payload, using the v1 signing scheme.
89 90 91 |
# File 'lib/helo/webhook_signatures.rb', line 89 def generate(payload, key, ) OpenSSL::HMAC.hexdigest("SHA256", key, "#{}.#{payload}") end |
.valid?(signature_header, request_body, signing_key) ⇒ Boolean
Verify a webhook signature header, returning false instead of raising.
76 77 78 79 80 |
# File 'lib/helo/webhook_signatures.rb', line 76 def valid?(signature_header, request_body, signing_key) verify!(signature_header, request_body, signing_key) rescue Error false end |
.verify!(signature_header, request_body, signing_key) ⇒ true
Verify a webhook signature header against the raw request body.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/helo/webhook_signatures.rb', line 47 def verify!(signature_header, request_body, signing_key) , signatures = parse_header(signature_header) version = newest_supported_version(signatures) unless version raise UnsupportedVersionError, "Unsupported webhook signature version: header carries only " \ "#{signatures.keys.sort.map { |v| "v#{v}" }.join(', ')}" end skew = (Time.now.to_i - .to_i).abs if skew > MAX_TIMESTAMP_SKEW_SECONDS raise TimestampSkewError, "Webhook signature timestamp outside tolerance: off by #{skew}s, " \ "tolerance is #{MAX_TIMESTAMP_SKEW_SECONDS}s" end computed = signature_for_version(version, request_body, signing_key, ) unless signatures.fetch(version).any? { |signature| secure_compare(computed, signature) } raise SignatureMismatchError, "Webhook signature mismatch" end true end |