Skip to content

Commit

Permalink
Merge pull request #173 from carsonreinke/hmac_signature
Browse files Browse the repository at this point in the history
Changed signature validation to HMAC-SHA256 per API change
  • Loading branch information
csaunders committed Apr 24, 2015
2 parents 37f57ae + 56c9765 commit d1a5e04
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 12 deletions.
7 changes: 4 additions & 3 deletions lib/shopify_api/session.rb
@@ -1,3 +1,4 @@
require 'openssl'

module ShopifyAPI

Expand Down Expand Up @@ -43,10 +44,10 @@ def prepare_url(url)

def validate_signature(params)
params = params.with_indifferent_access
return false unless signature = params[:signature]
return false unless signature = params[:hmac]

sorted_params = params.except(:signature, :action, :controller).collect{|k,v|"#{k}=#{v}"}.sort.join
Digest::MD5.hexdigest(secret + sorted_params) == signature
sorted_params = params.except(:signature, :hmac, :action, :controller).collect{|k,v|"#{k}=#{v}"}.sort.join('&')
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new(), secret, sorted_params) == signature
end

def host_with_port(site)
Expand Down
18 changes: 9 additions & 9 deletions test/session_test.rb
Expand Up @@ -117,51 +117,51 @@ class SessionTest < Test::Unit::TestCase
ShopifyAPI::Session.secret = 'secret'
params = {:code => 'any-code', :timestamp => Time.now}
sorted_params = make_sorted_params(params)
signature = Digest::MD5.hexdigest(ShopifyAPI::Session.secret + sorted_params)
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new(), ShopifyAPI::Session.secret, sorted_params)
fake nil, :url => 'https://testshop.myshopify.com/admin/oauth/access_token',:method => :post, :body => '{"access_token" : "any-token"}'
session = ShopifyAPI::Session.new("testshop.myshopify.com")
token = session.request_token(params.merge(:signature => signature))
token = session.request_token(params.merge(:hmac => signature))
assert_equal "any-token", token
end

should "raise error if signature does not match expected" do
ShopifyAPI::Session.secret = 'secret'
params = {:code => "any-code", :timestamp => Time.now}
sorted_params = make_sorted_params(params)
signature = Digest::MD5.hexdigest(ShopifyAPI::Session.secret + sorted_params)
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new(), ShopifyAPI::Session.secret, sorted_params)
params[:foo] = 'world'
assert_raises(ShopifyAPI::ValidationException) do
session = ShopifyAPI::Session.new("testshop.myshopify.com")
session.request_token(params.merge(:signature => signature))
session.request_token(params.merge(:hmac => signature))
end
end

should "raise error if timestamp is too old" do
ShopifyAPI::Session.secret = 'secret'
params = {:code => "any-code", :timestamp => Time.now - 2.days}
sorted_params = make_sorted_params(params)
signature = Digest::MD5.hexdigest(ShopifyAPI::Session.secret + sorted_params)
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new(), ShopifyAPI::Session.secret, sorted_params)
params[:foo] = 'world'
assert_raises(ShopifyAPI::ValidationException) do
session = ShopifyAPI::Session.new("testshop.myshopify.com")
session.request_token(params.merge(:signature => signature))
session.request_token(params.merge(:hmac => signature))
end
end

should "return true when the signature is valid and the keys of params are strings" do
now = Time.now
params = {"code" => "any-code", "timestamp" => now}
sorted_params = make_sorted_params(params)
signature = Digest::MD5.hexdigest(ShopifyAPI::Session.secret + sorted_params)
params = {"code" => "any-code", "timestamp" => now, "signature" => signature}
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new(), ShopifyAPI::Session.secret, sorted_params)
params = {"code" => "any-code", "timestamp" => now, "hmac" => signature}

assert_equal true, ShopifyAPI::Session.validate_signature(params)
end

private

def make_sorted_params(params)
sorted_params = params.with_indifferent_access.except(:signature, :action, :controller).collect{|k,v|"#{k}=#{v}"}.sort.join
sorted_params = params.with_indifferent_access.except(:signature, :hmac, :action, :controller).collect{|k,v|"#{k}=#{v}"}.sort.join('&')
end

end
Expand Down

0 comments on commit d1a5e04

Please sign in to comment.