Class: Hooksmith::Verifiers::Hmac
- Defined in:
- lib/hooksmith/verifiers/hmac.rb
Overview
HMAC-based webhook signature verifier.
This verifier validates webhook requests using HMAC signatures, which is a common authentication method used by providers like Stripe, GitHub, Shopify, and many others.
Constant Summary collapse
- ALGORITHMS =
Supported HMAC algorithms
%w[sha1 sha256 sha384 sha512].freeze
- DEFAULT_ENCODING =
Default signature encoding
:hex
Instance Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
-
#enabled? ⇒ Boolean
Returns whether the verifier is properly configured.
-
#initialize(secret:, header:, **options) ⇒ Hmac
constructor
Initializes the HMAC verifier.
-
#verify!(request) ⇒ void
Verifies the HMAC signature of the request.
Constructor Details
#initialize(secret:, header:, **options) ⇒ Hmac
Initializes the HMAC verifier.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/hooksmith/verifiers/hmac.rb', line 53 def initialize(secret:, header:, **) # Extract known options and pass remaining to parent (avoids ActiveSupport dependency) known_keys = i[algorithm encoding signature_prefix ] # rubocop:disable Style/HashExcept -- intentionally avoiding ActiveSupport's Hash#except = .reject { |k, _| known_keys.include?(k) } # rubocop:enable Style/HashExcept super(**) @secret = secret @header = header @algorithm = validate_algorithm(.fetch(:algorithm, 'sha256')) @encoding = .fetch(:encoding, DEFAULT_ENCODING) @signature_prefix = [:signature_prefix] ([:timestamp_options]) end |
Instance Method Details
#enabled? ⇒ Boolean
Returns whether the verifier is properly configured.
89 90 91 |
# File 'lib/hooksmith/verifiers/hmac.rb', line 89 def enabled? !@secret.nil? && !@secret.empty? && !@header.nil? && !@header.empty? end |
#verify!(request) ⇒ void
This method returns an undefined value.
Verifies the HMAC signature of the request.
73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/hooksmith/verifiers/hmac.rb', line 73 def verify!(request) signature = extract_signature(request) raise VerificationError.new('Missing signature header', reason: 'missing_signature') if signature.nil? (request) if expected = compute_signature(request.body) return if secure_compare(expected, signature) raise VerificationError.new('Invalid signature', reason: 'signature_mismatch') end |