omniauth-shopify-oauth2 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3c2fdff942824597bca290d63c4d5f2e8ad3fea3
4
- data.tar.gz: 175291a1282389126084a7d32c2fd7c4965faa9c
2
+ SHA256:
3
+ metadata.gz: a323c0e91f3f9574a06a0510f3a68e3ac0d0fefd52a9202d1d7899005ed3fa33
4
+ data.tar.gz: 3fb6661fe5e570d77070bdac24f88577c53a36b5fd847955dbf9368491620d28
5
5
  SHA512:
6
- metadata.gz: f905cd84cc0df6a8b1ef9d61ae432e0aaeb2d88547b77e4ddf5ca09c991ef181d131690a5ec6022553ff31b1246875cc76fd7420911cb463d021f459a72b8b4b
7
- data.tar.gz: e909527c818473c35ae5e9caf4f3afaffe38e9fdf835fc7bff13fe41c1be8ab2e81f71f1fca02011013d78303d1baccb222fb9e2c6cd7be9704fd9645c668e31
6
+ metadata.gz: 8f4909d9271c0b50bade9ea456594275aee7ee4877c6d89c55c9cae824e6b63c9659fecf945cfa6cc44ac3bdc67c1ae8961289b6a84f4683f2874419846fbcfc
7
+ data.tar.gz: d4df88d5a00976d50b2137f213ac6f64ff9ea011538a835d7e63204a3b5cdafc9b2f000947652de0ad0407a8ef37a9710b94495a8a3fe7aa175aaff77a89679d
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module Shopify
3
- VERSION = "2.0.0"
3
+ VERSION = "2.1.0"
4
4
  end
5
5
  end
@@ -17,6 +17,7 @@ module OmniAuth
17
17
 
18
18
  option :callback_url
19
19
  option :myshopify_domain, 'myshopify.com'
20
+ option :old_client_secret
20
21
 
21
22
  # When `true`, the user's permission level will apply (in addition to
22
23
  # the requested access scope) when making API requests to Shopify.
@@ -61,8 +62,10 @@ module OmniAuth
61
62
 
62
63
  return false unless timestamp.to_i > Time.now.to_i - CODE_EXPIRES_AFTER
63
64
 
64
- calculated_signature = self.class.hmac_sign(self.class.encoded_params_for_signature(params), options.client_secret)
65
- Rack::Utils.secure_compare(calculated_signature, signature)
65
+ new_secret = options.client_secret
66
+ old_secret = options.old_client_secret
67
+
68
+ validate_signature(new_secret) || (old_secret && validate_signature(old_secret))
66
69
  end
67
70
 
68
71
  def valid_scope?(token)
@@ -139,6 +142,14 @@ module OmniAuth
139
142
  def callback_url
140
143
  options[:callback_url] || full_host + script_name + callback_path
141
144
  end
145
+
146
+ private
147
+
148
+ def validate_signature(secret)
149
+ params = request.GET
150
+ calculated_signature = self.class.hmac_sign(self.class.encoded_params_for_signature(params), secret)
151
+ Rack::Utils.secure_compare(calculated_signature, params['hmac'])
152
+ end
142
153
  end
143
154
  end
144
155
  end
@@ -52,7 +52,7 @@ class IntegrationTest < Minitest::Test
52
52
  response = authorize(shop)
53
53
  assert_auth_failure(response, 'invalid_site')
54
54
 
55
- response = callback(sign_params(shop: shop, code: code))
55
+ response = callback(sign_with_new_secret(shop: shop, code: code))
56
56
  assert_auth_failure(response, 'invalid_site')
57
57
  end
58
58
  end
@@ -62,7 +62,7 @@ class IntegrationTest < Minitest::Test
62
62
  code = SecureRandom.hex(16)
63
63
  expect_access_token_request(access_token, OmniAuth::Strategies::Shopify::DEFAULT_SCOPE)
64
64
 
65
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
65
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
66
66
 
67
67
  assert_callback_success(response, access_token, code)
68
68
  end
@@ -73,7 +73,7 @@ class IntegrationTest < Minitest::Test
73
73
  code = SecureRandom.hex(16)
74
74
  expect_access_token_request(access_token, OmniAuth::Strategies::Shopify::DEFAULT_SCOPE)
75
75
 
76
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]).merge(signature: 'ignored'))
76
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]).merge(signature: 'ignored'))
77
77
 
78
78
  assert_callback_success(response, access_token, code)
79
79
  end
@@ -100,21 +100,21 @@ class IntegrationTest < Minitest::Test
100
100
  code = SecureRandom.hex(16)
101
101
  expect_access_token_request(access_token, 'read_orders,write_products')
102
102
 
103
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
103
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
104
104
 
105
105
  assert_callback_success(response, access_token, code)
106
106
  end
107
107
 
108
108
  def test_callback_rejects_invalid_hmac
109
109
  @secret = 'wrong_secret'
110
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: SecureRandom.hex(16)))
110
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: SecureRandom.hex(16)))
111
111
 
112
112
  assert_auth_failure(response, 'invalid_signature')
113
113
  end
114
114
 
115
115
  def test_callback_rejects_old_timestamps
116
116
  expired_timestamp = Time.now.to_i - OmniAuth::Strategies::Shopify::CODE_EXPIRES_AFTER - 1
117
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: SecureRandom.hex(16), timestamp: expired_timestamp))
117
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: SecureRandom.hex(16), timestamp: expired_timestamp))
118
118
 
119
119
  assert_auth_failure(response, 'invalid_signature')
120
120
  end
@@ -129,7 +129,7 @@ class IntegrationTest < Minitest::Test
129
129
 
130
130
  def test_callback_rejects_body_params
131
131
  code = SecureRandom.hex(16)
132
- params = sign_params(shop: 'snowdevil.myshopify.com', code: code)
132
+ params = sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code)
133
133
  body = Rack::Utils.build_nested_query(unsigned: 'value')
134
134
 
135
135
  response = request.get("https://app.example.com/auth/shopify/callback?#{Rack::Utils.build_query(params)}",
@@ -189,7 +189,7 @@ class IntegrationTest < Minitest::Test
189
189
  code = SecureRandom.hex(16)
190
190
  expect_access_token_request(access_token, OmniAuth::Strategies::Shopify::DEFAULT_SCOPE)
191
191
 
192
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: 'invalid'))
192
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: 'invalid'))
193
193
 
194
194
  assert_equal 302, response.status
195
195
  assert_equal '/auth/failure?message=csrf_detected&strategy=shopify', response.location
@@ -200,7 +200,7 @@ class IntegrationTest < Minitest::Test
200
200
  code = SecureRandom.hex(16)
201
201
  expect_access_token_request(access_token, 'some_invalid_scope', nil)
202
202
 
203
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
203
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
204
204
 
205
205
  assert_equal 302, response.status
206
206
  assert_equal '/auth/failure?message=invalid_scope&strategy=shopify', response.location
@@ -211,7 +211,7 @@ class IntegrationTest < Minitest::Test
211
211
  code = SecureRandom.hex(16)
212
212
  expect_access_token_request(access_token, nil)
213
213
 
214
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
214
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
215
215
 
216
216
  assert_equal 302, response.status
217
217
  assert_equal '/auth/failure?message=invalid_scope&strategy=shopify', response.location
@@ -224,7 +224,7 @@ class IntegrationTest < Minitest::Test
224
224
  code = SecureRandom.hex(16)
225
225
  expect_access_token_request(access_token, 'first_scope')
226
226
 
227
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
227
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
228
228
 
229
229
  assert_equal 302, response.status
230
230
  assert_equal '/auth/failure?message=invalid_scope&strategy=shopify', response.location
@@ -237,7 +237,7 @@ class IntegrationTest < Minitest::Test
237
237
  code = SecureRandom.hex(16)
238
238
  expect_access_token_request(access_token, 'second_scope,first_scope,third_scope')
239
239
 
240
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
240
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
241
241
 
242
242
  assert_equal 302, response.status
243
243
  assert_equal '/auth/failure?message=invalid_scope&strategy=shopify', response.location
@@ -250,7 +250,7 @@ class IntegrationTest < Minitest::Test
250
250
  code = SecureRandom.hex(16)
251
251
  expect_access_token_request(access_token, 'second_scope,first_scope')
252
252
 
253
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
253
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
254
254
 
255
255
  assert_callback_success(response, access_token, code)
256
256
  end
@@ -262,7 +262,7 @@ class IntegrationTest < Minitest::Test
262
262
  code = SecureRandom.hex(16)
263
263
  expect_access_token_request(access_token, 'read_content,write_products')
264
264
 
265
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
265
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
266
266
 
267
267
  assert_callback_success(response, access_token, code)
268
268
  end
@@ -274,7 +274,7 @@ class IntegrationTest < Minitest::Test
274
274
  code = SecureRandom.hex(16)
275
275
  expect_access_token_request(access_token, 'scope', { id: 1, email: 'bob@bobsen.com'})
276
276
 
277
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
277
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
278
278
 
279
279
  assert_equal 302, response.status
280
280
  assert_equal '/auth/failure?message=invalid_permissions&strategy=shopify', response.location
@@ -287,7 +287,7 @@ class IntegrationTest < Minitest::Test
287
287
  code = SecureRandom.hex(16)
288
288
  expect_access_token_request(access_token, 'scope', nil)
289
289
 
290
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
290
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
291
291
 
292
292
  assert_equal 302, response.status
293
293
  assert_equal '/auth/failure?message=invalid_permissions&strategy=shopify', response.location
@@ -300,18 +300,45 @@ class IntegrationTest < Minitest::Test
300
300
  code = SecureRandom.hex(16)
301
301
  expect_access_token_request(access_token, 'scope', { id: 1, email: 'bob@bobsen.com'})
302
302
 
303
- response = callback(sign_params(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
303
+ response = callback(sign_with_new_secret(shop: 'snowdevil.myshopify.com', code: code, state: opts["rack.session"]["omniauth.state"]))
304
304
 
305
305
  assert_equal 200, response.status
306
306
  end
307
307
 
308
+ def test_callback_works_with_old_secret
309
+ build_app scope: OmniAuth::Strategies::Shopify::DEFAULT_SCOPE
310
+ access_token = SecureRandom.hex(16)
311
+ code = SecureRandom.hex(16)
312
+ expect_access_token_request(access_token, OmniAuth::Strategies::Shopify::DEFAULT_SCOPE)
313
+
314
+ signed_params = sign_with_old_secret(
315
+ shop: 'snowdevil.myshopify.com',
316
+ code: code,
317
+ state: opts["rack.session"]["omniauth.state"]
318
+ )
319
+
320
+ response = callback(signed_params)
321
+
322
+ assert_callback_success(response, access_token, code)
323
+ end
324
+
308
325
  private
309
326
 
310
- def sign_params(params)
311
- params = params.dup
327
+ def sign_with_old_secret(params)
328
+ params = add_time(params)
329
+ encoded_params = OmniAuth::Strategies::Shopify.encoded_params_for_signature(params)
330
+ params['hmac'] = OmniAuth::Strategies::Shopify.hmac_sign(encoded_params, @old_secret)
331
+ params
332
+ end
312
333
 
334
+ def add_time(params)
335
+ params = params.dup
313
336
  params[:timestamp] ||= Time.now.to_i
337
+ params
338
+ end
314
339
 
340
+ def sign_with_new_secret(params)
341
+ params = add_time(params)
315
342
  encoded_params = OmniAuth::Strategies::Shopify.encoded_params_for_signature(params)
316
343
  params['hmac'] = OmniAuth::Strategies::Shopify.hmac_sign(encoded_params, @secret)
317
344
  params
@@ -344,6 +371,9 @@ class IntegrationTest < Minitest::Test
344
371
  end
345
372
 
346
373
  def build_app(options={})
374
+ @old_secret = '12d34s1'
375
+ @secret = '53cr3tz'
376
+ options.merge!(old_client_secret: @old_secret)
347
377
  app = proc { |env|
348
378
  @omniauth_result = env['omniauth.auth']
349
379
  [200, {Rack::CONTENT_TYPE => "text/plain"}, "OK"]
@@ -351,9 +381,8 @@ class IntegrationTest < Minitest::Test
351
381
 
352
382
  opts["rack.session"]["omniauth.state"] = SecureRandom.hex(32)
353
383
  app = OmniAuth::Builder.new(app) do
354
- provider :shopify, '123', '53cr3tz', options
384
+ provider :shopify, '123', '53cr3tz' , options
355
385
  end
356
- @secret = '53cr3tz'
357
386
  @app = Rack::Session::Cookie.new(app, secret: SecureRandom.hex(64))
358
387
  end
359
388
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-shopify-oauth2
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Odorcic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-14 00:00:00.000000000 Z
11
+ date: 2019-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: omniauth-oauth2
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  version: '0'
125
125
  requirements: []
126
126
  rubyforge_project:
127
- rubygems_version: 2.6.14
127
+ rubygems_version: 2.7.6
128
128
  signing_key:
129
129
  specification_version: 4
130
130
  summary: Shopify strategy for OmniAuth