You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
docuseal/lib/webhook_urls/signatures.rb

41 lines
1.1 KiB

# frozen_string_literal: true
module WebhookUrls
module Signatures
SECRET_PREFIX = 'whsec_'
SECRET_BYTES = 24
TOLERANCE = 5 * 60
InvalidSignatureError = Class.new(StandardError)
TimestampError = Class.new(StandardError)
module_function
def generate_secret
SECRET_PREFIX + Base64.strict_encode64(SecureRandom.bytes(SECRET_BYTES))
end
def sign(secret, body:, timestamp: Time.current.to_i)
"#{timestamp}.#{OpenSSL::HMAC.hexdigest('sha256', secret, "#{timestamp}.#{body}")}"
end
def verify(secret, body:, header:, tolerance: TOLERANCE)
ts, sig = header.to_s.split('.', 2)
ts = Integer(ts, exception: false)
raise InvalidSignatureError unless ts && sig
now = Time.current.to_i
raise TimestampError, 'Too old' if ts < now - tolerance
raise TimestampError, 'In future' if ts > now + tolerance
expected = OpenSSL::HMAC.hexdigest('sha256', secret, "#{ts}.#{body}")
raise InvalidSignatureError unless ActiveSupport::SecurityUtils.secure_compare(expected, sig)
true
end
end
end