lib/ey-hmac/adapter.rb in ey-hmac-2.3.1 vs lib/ey-hmac/adapter.rb in ey-hmac-2.4.0

- old
+ new

@@ -2,40 +2,53 @@ # This class is responsible for forming the canonical string to used to sign requests # @abstract override methods {#method}, {#path}, {#body}, {#content_type} and {#content_digest} class Ey::Hmac::Adapter AUTHORIZATION_REGEXP = /\w+ ([^:]+):(.+)$/.freeze + DEFAULT_CANONICALIZE_WITH = %i[method content_type content_digest date path].freeze autoload :Rack, 'ey-hmac/adapter/rack' autoload :Faraday, 'ey-hmac/adapter/faraday' - attr_reader :request, :options, :authorization_header, :service, :sign_with, :accept_digests + attr_reader :request, + :options, + :authorization_header, + :service, + :sign_with, + :accept_digests, + :include_query_string, + :canonicalize_with # @param [Object] request signer-specific request implementation # @option options [Integer] :version signature version # @option options [Integer] :ttl (nil) duration during which HMAC is valid after signed date # @option options [String] :authorization_header ('Authorization') Authorization header key. # @option options [String] :server ('EyHmac') service name prefixed to {#authorization}. set to {#service} # @option options [Symbol] :sign_with (:sha_256) outgoing signature digest algorithm. See {OpenSSL::Digest#new} + # @option options [Symbol] :include_query_string (false) canonicalize with the request query string. # @option options [Array] :accepted_digests ([:sha_256]) accepted incoming signature digest algorithm. See {OpenSSL::Digest#new} def initialize(request, options = {}) @request = request @options = options @ttl = options[:ttl] @authorization_header = options[:authorization_header] || 'Authorization' @service = options[:service] || 'EyHmac' @sign_with = options[:sign_with] || :sha256 - @accept_digests = Array(options[:accept_digests] || :sha256) + @include_query_string = options.fetch(:include_query_string, false) + @accept_digests = Array(options[:accept_digests] || :sha256) + + @canonicalize_with = DEFAULT_CANONICALIZE_WITH + @canonicalize_with += :query_string if include_query_string end # In order for the server to correctly authorize the request, the client and server MUST AGREE on this format # # default canonical string formation is '{#method}\\n{#content_type}\\n{#content_digest}\\n{#date}\\n{#path}' # @return [String] canonical string used to form the {#signature} def canonicalize - [method, content_type, content_digest, date, path].join("\n") + canonicalize_with.map { |message| public_send(message) }.join("\n") end # @param [String] key_secret private HMAC key # @param [String] signature digest hash function. Defaults to #sign_with # @return [String] HMAC signature of {#request} @@ -127,11 +140,14 @@ "Failed to find secret matching #{key_id.inspect}" end check_ttl! - calculated_signatures = accept_digests.map { |ad| signature(key_secret, ad) } - matching_signature = calculated_signatures.any? { |cs| secure_compare(signature_value, cs) } + matching_signature = + accept_digests + .lazy + .map { |ad| signature(key_secret, ad) } + .any? { |cs| secure_compare(signature_value, cs) } raise Ey::Hmac::SignatureMismatch unless matching_signature true end