Class: Webhookdb::Increase
- Inherits:
-
Object
- Object
- Webhookdb::Increase
- Extended by:
- MethodUtilities
- Includes:
- Appydays::Configurable, Appydays::Loggable
- Defined in:
- lib/webhookdb/increase.rb
Defined Under Namespace
Classes: WebhookSignature
Constant Summary collapse
- OLD_CUTOFF =
35.days
- NEW_CUTOFF =
4.days
Class Method Summary collapse
- .compute_signature(secret:, data:, t:) ⇒ WebhookSignature
- .parse_signature(s) ⇒ WebhookSignature
- .webhook_response(request, webhook_secret, now: Time.now) ⇒ Object
Methods included from MethodUtilities
attr_predicate, attr_predicate_accessor, singleton_attr_accessor, singleton_attr_reader, singleton_attr_writer, singleton_method_alias, singleton_predicate_accessor, singleton_predicate_reader
Class Method Details
.compute_signature(secret:, data:, t:) ⇒ WebhookSignature
62 63 64 65 66 |
# File 'lib/webhookdb/increase.rb', line 62 def self.compute_signature(secret:, data:, t:) signed_payload = "#{t.utc.iso8601}.#{data}" sig = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), secret, signed_payload) return WebhookSignature.new(v1: [sig], t:) end |
.parse_signature(s) ⇒ WebhookSignature
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/webhookdb/increase.rb', line 41 def self.parse_signature(s) sig = WebhookSignature.new s&.split(",")&.each do |part| key, val = part.split("=") if key == "t" begin sig.t = Time.rfc3339(val) rescue ArgumentError nil end elsif key == "v1" sig.v1 << val end end return sig end |
.webhook_response(request, webhook_secret, now: Time.now) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/webhookdb/increase.rb', line 71 def self.webhook_response(request, webhook_secret, now: Time.now) http_signature = request.env["HTTP_INCREASE_WEBHOOK_SIGNATURE"] return Webhookdb::WebhookResponse.error("missing header") if http_signature.nil? request.body.rewind request_data = request.body.read parsed_signature = self.parse_signature(http_signature) return Webhookdb::WebhookResponse.error("missing timestamp") if parsed_signature.t.nil? return Webhookdb::WebhookResponse.error("missing signatures") if parsed_signature.v1.empty? return Webhookdb::WebhookResponse.error("too old") if parsed_signature.t < (now - OLD_CUTOFF) return Webhookdb::WebhookResponse.error("too new") if parsed_signature.t > (now + NEW_CUTOFF) computed_signature = self.compute_signature(secret: webhook_secret, data: request_data, t: parsed_signature.t) return Webhookdb::WebhookResponse.error("invalid signature") unless parsed_signature.v1.include?(computed_signature.v1.first) return Webhookdb::WebhookResponse.ok end |