Module: Broadcast::Webhook
- Defined in:
- lib/broadcast/webhook.rb
Constant Summary collapse
- TIMESTAMP_TOLERANCE =
5 minutes
300
Class Method Summary collapse
- .compute_signature(payload, timestamp, secret) ⇒ Object
- .extract_signature(header) ⇒ Object
- .secure_compare(a, b) ⇒ Object
- .timestamp_valid?(timestamp, current_time = Time.now.to_i) ⇒ Boolean
- .verify(payload, signature_header, timestamp_header, secret:, now: nil) ⇒ Object
Class Method Details
.compute_signature(payload, timestamp, secret) ⇒ Object
26 27 28 29 30 |
# File 'lib/broadcast/webhook.rb', line 26 def compute_signature(payload, , secret) signed_content = "#{}.#{payload}" hmac = OpenSSL::HMAC.digest('SHA256', secret, signed_content) Base64.strict_encode64(hmac) end |
.extract_signature(header) ⇒ Object
36 37 38 39 40 41 42 43 |
# File 'lib/broadcast/webhook.rb', line 36 def extract_signature(header) return nil unless header&.start_with?('v1,') sig = header.delete_prefix('v1,') return nil if sig.empty? sig end |
.secure_compare(a, b) ⇒ Object
45 46 47 48 49 |
# File 'lib/broadcast/webhook.rb', line 45 def secure_compare(a, b) return false unless a.bytesize == b.bytesize OpenSSL.fixed_length_secure_compare(a, b) end |
.timestamp_valid?(timestamp, current_time = Time.now.to_i) ⇒ Boolean
32 33 34 |
# File 'lib/broadcast/webhook.rb', line 32 def (, current_time = Time.now.to_i) (current_time - ).abs <= TIMESTAMP_TOLERANCE end |
.verify(payload, signature_header, timestamp_header, secret:, now: nil) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/broadcast/webhook.rb', line 12 def verify(payload, signature_header, , secret:, now: nil) return false if payload.nil? || signature_header.nil? || .nil? || secret.nil? = .to_i current_time = (now || Time.now).to_i return false unless (, current_time) expected = compute_signature(payload, , secret) actual = extract_signature(signature_header) return false if actual.nil? secure_compare(expected, actual) end |