ソースを参照

prefactor: extract hmac-related param handling

Add tests describing the encoding behaviors for keys and values during
signature validation. These tests are _descriptive_ of the current
behavior, and not _prescriptive_.
Mike Dalessio 3 年 前
コミット
f1116f9af2

+ 1 - 0
lib/shopify_api.rb

@@ -21,6 +21,7 @@ require 'shopify_api/metafields'
 require 'shopify_api/countable'
 require 'shopify_api/resources'
 require 'shopify_api/session'
+require 'shopify_api/hmac_params'
 require 'shopify_api/api_access'
 require 'shopify_api/message_enricher'
 require 'shopify_api/connection'

+ 22 - 0
lib/shopify_api/hmac_params.rb

@@ -0,0 +1,22 @@
+require 'webrick/httputils'
+
+module ShopifyAPI
+  module HmacParams
+    extend WEBrick::HTTPUtils
+
+    def self.encode(params)
+      params
+        .except(:signature, :hmac, :action, :controller)
+        .map { |k,v| sprintf("%s=%s", encode_key(k), encode_value(v)) }
+        .sort.join("&")
+    end
+
+    def self.encode_key(key)
+      URI.escape(key.to_s, '&=%')
+    end
+
+    def self.encode_value(value)
+      URI.escape(value.to_s, '&%')
+    end
+  end
+end

+ 1 - 6
lib/shopify_api/session.rb

@@ -71,7 +71,7 @@ module ShopifyAPI
         return false unless (signature = params[:hmac])
 
         calculated_signature = OpenSSL::HMAC.hexdigest(
-          OpenSSL::Digest.new('SHA256'), secret, encoded_params_for_signature(params)
+          OpenSSL::Digest.new('SHA256'), secret, ShopifyAPI::HmacParams.encode(params)
         )
 
         Rack::Utils.secure_compare(calculated_signature, signature)
@@ -79,11 +79,6 @@ module ShopifyAPI
 
       private
 
-      def encoded_params_for_signature(params)
-        params = params.except(:signature, :hmac, :action, :controller)
-        params.map { |k, v| "#{URI.escape(k.to_s, '&=%')}=#{URI.escape(v.to_s, '&%')}" }.sort.join('&')
-      end
-
       def extract_current_session
         site = ShopifyAPI::Base.site.to_s
         token = ShopifyAPI::Base.headers['X-Shopify-Access-Token']

+ 25 - 0
test/hmac_params_test.rb

@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+require 'test_helper'
+
+class HmacParamsTest < Test::Unit::TestCase
+  test "cgi param keys are prepared for hmac validation by encoding equals, ampersand, and percent characters" do
+    assert_equal(
+      "abcd%26%3D%251234",
+      ShopifyAPI::HmacParams.encode_key("abcd&=%1234")
+    )
+  end
+
+  test "cgi param values are prepared for hmac validation by encoding ampersand and percent characters" do
+    assert_equal(
+      "abcd%26=%251234",
+      ShopifyAPI::HmacParams.encode_value("abcd&=%1234")
+    )
+  end
+
+  test "cgi params are encoded properly for hmac validation" do
+    assert_equal(
+      "abcd%26%3D%251234=abcd%26=%251234",
+      ShopifyAPI::HmacParams.encode({"abcd&=%1234" => "abcd&=%1234"})
+    )
+  end
+end