Class: StandardWebhooks::Webhook

Inherits:
Object
  • Object
show all
Defined in:
lib/standard_webhooks.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(secret) ⇒ Webhook

Returns a new instance of Webhook.



64
65
66
67
68
69
70
# File 'lib/standard_webhooks.rb', line 64

def initialize(secret)
  if secret.start_with?(SECRET_PREFIX)
    secret = secret[SECRET_PREFIX.length..-1]
  end

  @secret = Base64.decode64(secret)
end

Class Method Details

.new_using_raw_bytes(secret) ⇒ Object



60
61
62
# File 'lib/standard_webhooks.rb', line 60

def self.new_using_raw_bytes(secret)
  self.new(secret.pack("C*").force_encoding("UTF-8"))
end

Instance Method Details

#sign(msg_id, timestamp, payload) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/standard_webhooks.rb', line 102

def sign(msg_id, timestamp, payload)
  begin
    now = Integer(timestamp)
  rescue
    raise WebhookSigningError, "Invalid timestamp"
  end

  to_sign = "#{msg_id}.#{timestamp}.#{payload}"
  signature = Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new("sha256"), @secret, to_sign)).strip

  return "v1,#{signature}"
end

#verify(payload, headers) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/standard_webhooks.rb', line 72

def verify(payload, headers)
  msg_id = headers["webhook-id"]
  msg_signature = headers["webhook-signature"]
  msg_timestamp = headers["webhook-timestamp"]

  if !msg_signature || !msg_id || !msg_timestamp
    raise WebhookVerificationError, "Missing required headers"
  end

  verify_timestamp(msg_timestamp)

  _, signature = sign(msg_id, msg_timestamp, payload).split(",", 2)

  passed_signatures = msg_signature.split(" ")

  passed_signatures.each do |versioned_signature|
    version, expected_signature = versioned_signature.split(",", 2)

    if version != "v1"
      next
    end

    if ::StandardWebhooks::secure_compare(signature, expected_signature)
      return JSON.parse(payload, symbolize_names: true)
    end
  end

  raise WebhookVerificationError, "No matching signature found"
end