Module: BulletTrain::OutgoingWebhooks::Signature
- Defined in:
- lib/bullet_train/outgoing_webhooks/signature.rb
Overview
Provides methods for webhook signatures. This module also serves as an example that can be used by receiving applications to verify webhook authenticity.
Class Method Summary collapse
-
.generate(payload, secret) ⇒ Object
Algorithm to generate the signature.
-
.verify(payload, signature, timestamp, secret) ⇒ Boolean
Verifies the authenticity of a webhook request.
-
.verify_request(request, secret) ⇒ Boolean
A Rails controller helper example to verify webhook requests.
Class Method Details
.generate(payload, secret) ⇒ Object
Algorithm to generate the signature.
56 57 58 59 60 61 62 63 64 65 |
# File 'lib/bullet_train/outgoing_webhooks/signature.rb', line 56 def self.generate(payload, secret) = Time.now.to_i.to_s signature_payload = "#{}.#{payload.to_json}" signature = OpenSSL::HMAC.hexdigest("SHA256", secret, signature_payload) { signature: signature, timestamp: } end |
.verify(payload, signature, timestamp, secret) ⇒ Boolean
Verifies the authenticity of a webhook request.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/bullet_train/outgoing_webhooks/signature.rb', line 14 def self.verify(payload, signature, , secret) return false if payload.blank? || signature.blank? || .blank? || secret.blank? tolerance = Rails.configuration.outgoing_webhooks[:event_verification_tolerance_seconds] # Check if the timestamp is too old = .to_i now = Time.now.to_i if (now - ).abs > tolerance return false # Webhook is too old or timestamp is from the future end # Compute the expected signature signature_payload = "#{}.#{payload}" expected_signature = OpenSSL::HMAC.hexdigest("SHA256", secret, signature_payload) # Compare signatures using constant-time comparison to prevent timing attacks ActiveSupport::SecurityUtils.secure_compare(expected_signature, signature) end |
.verify_request(request, secret) ⇒ Boolean
A Rails controller helper example to verify webhook requests.
39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/bullet_train/outgoing_webhooks/signature.rb', line 39 def self.verify_request(request, secret) return false if request.blank? || secret.blank? webhook_headers_namespace = Rails.configuration.outgoing_webhooks[:webhook_headers_namespace] signature = request.headers["#{webhook_headers_namespace}-Signature"] = request.headers["#{webhook_headers_namespace}-Timestamp"] payload = request.raw_post return false if signature.blank? || .blank? verify(payload, signature, , secret) end |