Class: Paymos::WebhookVerifier
- Inherits:
-
Object
- Object
- Paymos::WebhookVerifier
- Defined in:
- lib/paymos/webhook_verifier.rb,
sig/paymos.rbs
Instance Method Summary collapse
- #assert_valid(signature_header, raw_body, now: nil) ⇒ void
- #construct_event(signature_header, raw_body, now: nil) ⇒ WebhookEvent[Hash[String, untyped]]
-
#initialize(secret, tolerance: 300, clock: -> { Time.now.to_i }) ⇒ WebhookVerifier
constructor
A new instance of WebhookVerifier.
- #verify(signature_header, raw_body, now: nil) ⇒ Boolean
Constructor Details
#initialize(secret, tolerance: 300, clock: -> { Time.now.to_i }) ⇒ WebhookVerifier
Returns a new instance of WebhookVerifier.
9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/paymos/webhook_verifier.rb', line 9 def initialize(secret, tolerance: 300, clock: -> { Time.now.to_i }) unless secret.is_a?(String) && !secret.strip.empty? raise ArgumentError, 'Webhook secret must be a non-empty string' end raise ArgumentError, 'Webhook tolerance must be non-negative' unless tolerance.is_a?(Integer) && tolerance >= 0 @secret = secret @tolerance = tolerance @clock = clock end |
Instance Method Details
#assert_valid(signature_header, raw_body, now: nil) ⇒ void
This method returns an undefined value.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/paymos/webhook_verifier.rb', line 28 def assert_valid(signature_header, raw_body, now: nil) raise ArgumentError, 'Raw webhook body must be a string' unless raw_body.is_a?(String) , signatures = parse_header(signature_header) current = now.nil? ? @clock.call.to_i : now.to_i if (current - ).abs > @tolerance raise TimestampSkewError, 'Webhook timestamp is outside the allowed tolerance' end expected = OpenSSL::HMAC.hexdigest('SHA256', @secret, "#{}.#{raw_body}") valid = signatures.any? { |value| secure_compare(expected, value.downcase) } raise SignatureMismatchError, 'Webhook signature does not match payload' unless valid nil end |
#construct_event(signature_header, raw_body, now: nil) ⇒ WebhookEvent[Hash[String, untyped]]
45 46 47 48 49 50 |
# File 'lib/paymos/webhook_verifier.rb', line 45 def construct_event(signature_header, raw_body, now: nil) assert_valid(signature_header, raw_body, now: now) WebhookEvent.from(JSON.parse(raw_body)) rescue JSON::ParserError => e raise Error, "Webhook payload is invalid JSON: #{e.}" end |
#verify(signature_header, raw_body, now: nil) ⇒ Boolean
21 22 23 24 25 26 |
# File 'lib/paymos/webhook_verifier.rb', line 21 def verify(signature_header, raw_body, now: nil) assert_valid(signature_header, raw_body, now: now) true rescue SignatureMismatchError, TimestampSkewError false end |