shopify_app 8.4.2 → 8.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +9 -0
- data/README.md +26 -0
- data/config/locales/nl.yml +21 -0
- data/config/locales/zh-CN.yml +16 -0
- data/config/locales/zh-TW.yml +17 -0
- data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +3 -1
- data/lib/generators/shopify_app/install/install_generator.rb +2 -0
- data/lib/generators/shopify_app/install/templates/shopify_app.rb +1 -0
- data/lib/generators/shopify_app/install/templates/shopify_provider.rb +17 -14
- data/lib/generators/shopify_app/rotate_shopify_token_job/rotate_shopify_token_job_generator.rb +16 -0
- data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token.rake +17 -0
- data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token_job.rb +42 -0
- data/lib/shopify_app/configuration.rb +1 -0
- data/lib/shopify_app/controller_concerns/webhook_verification.rb +10 -6
- data/lib/shopify_app/version.rb +1 -1
- data/shopify_app.gemspec +1 -1
- data/translation.yml +1 -1
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8fe2949f5e38db4532dbcab3c05f96e228e6285fdbb4b729ffefecd8e40b2aad
|
4
|
+
data.tar.gz: 2fefc3ce45bc58cd82c874d5217f6abfce0a70ba56cb9105084dbec011f033cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a435b2541e5198fad47a247a97b2a68ce6e741b2b29a4b0b7f2cc29d256fc382a7fd8a56801e982744258e9efdfd3879a13dd4dffc033c88d432ce44d525e44
|
7
|
+
data.tar.gz: 1df140b61ca82e090eba2fcabac5f079cc5d87e7cb64bab657cbc725ff1063360fbd88822d4ed76c9224d2fd4e9429ba197dd3c7f6a6312b3c8dbdb060c35f26
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
8.5.0
|
2
|
+
-----
|
3
|
+
Added support for rotating Shopify access tokens:
|
4
|
+
|
5
|
+
* Added a generator shopify_app:rotate_shopify_token_job for generating the job to perform token rotation
|
6
|
+
* Extend Shopify app configuration to support a new and old secret token
|
7
|
+
* Extended webhook validation code to support validating against new and old secret tokens
|
8
|
+
* See the README for more details: https://github.com/Shopify/shopify_app#rotateshopifytokenjob
|
9
|
+
|
1
10
|
8.4.2
|
2
11
|
-----
|
3
12
|
* Clear stale user session during auth callback
|
data/README.md
CHANGED
@@ -364,6 +364,32 @@ We've also provided a generator which creates a skeleton job and updates the ini
|
|
364
364
|
bin/rails g shopify_app:add_after_authenticate_job
|
365
365
|
```
|
366
366
|
|
367
|
+
RotateShopifyTokenJob
|
368
|
+
---------------------
|
369
|
+
|
370
|
+
If your Shopify secret key is leaked, you can use the RotateShopifyTokenJob to perform [API Credential Rotation](https://help.shopify.com/en/api/getting-started/authentication/oauth/api-credential-rotation).
|
371
|
+
|
372
|
+
Before running the job, you'll need to generate a new secret key from your Shopify Partner dashboard, and update the `/config/initializers/shopify_app.rb` to hold your new and old secret keys:
|
373
|
+
|
374
|
+
```ruby
|
375
|
+
config.secret = Rails.application.secrets.shopify_secret
|
376
|
+
config.old_secret = Rails.application.secrets.old_shopify_secret
|
377
|
+
```
|
378
|
+
|
379
|
+
We've provided a generator which creates the job and an example rake task:
|
380
|
+
|
381
|
+
```sh
|
382
|
+
bin/rails g shopify_app:rotate_shopify_token_job
|
383
|
+
```
|
384
|
+
|
385
|
+
The generated rake task will be found at `lib/tasks/shopify/rotate_shopify_token.rake` and is provided strictly for example purposes. It might not work with your application out of the box without some configuration.
|
386
|
+
|
387
|
+
⚠️ Note: if you are updating `shopify_app` from a version prior to 8.4.2 (and do not wish to run the default/install generator again), you will need to add [the following line](https://github.com/Shopify/shopify_app/blob/4f7e6cca2a472d8f7af44b938bd0fcafe4d8e88a/lib/generators/shopify_app/install/templates/shopify_provider.rb#L18) to `config/intializers/omniauth.rb`:
|
388
|
+
|
389
|
+
```ruby
|
390
|
+
strategy.options[:old_client_secret] = ShopifyApp.configuration.old_secret
|
391
|
+
```
|
392
|
+
|
367
393
|
ShopifyApp::SessionRepository
|
368
394
|
-----------------------------
|
369
395
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
nl:
|
3
|
+
logged_out: U bent afgemeld
|
4
|
+
could_not_log_in: Kon niet aanmelden bij Shopify-winkel
|
5
|
+
invalid_shop_url: Ongeldig winkeldomein
|
6
|
+
enable_cookies_heading: Schakel cookies in van %{app}
|
7
|
+
enable_cookies_body: U moet cookies in deze browser handmatig inschakelen om %{app}
|
8
|
+
binnen Shopify te gebruiken.
|
9
|
+
enable_cookies_footer: Met cookies kan de app u verifiëren door uw voorkeuren en
|
10
|
+
persoonlijke informatie tijdelijk op te slaan. Ze vervallen na 30 dagen.
|
11
|
+
enable_cookies_action: Schakel cookies in
|
12
|
+
top_level_interaction_heading: Uw browser moet %{app} verifiëren
|
13
|
+
top_level_interaction_body: Uw browser heeft apps van derden nodig zoals %{app}
|
14
|
+
om u toegang te vragen tot cookies voordat Shopify het voor u kan openen.
|
15
|
+
top_level_interaction_action: Doorgaan
|
16
|
+
request_storage_access_heading: "%{app} heeft toegang tot cookies nodig"
|
17
|
+
request_storage_access_body: Hiermee kan de app u verifiëren door uw persoonlijke
|
18
|
+
gegevens tijdelijk op te slaan. Klik op Doorgaan en sta cookies toe om de app
|
19
|
+
te gebruiken.
|
20
|
+
request_storage_access_footer: Cookies verlopen na 30 dagen.
|
21
|
+
request_storage_access_action: Doorgaan
|
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
zh-CN:
|
3
|
+
logged_out: 已成功注销
|
4
|
+
could_not_log_in: 无法登录到 Shopify 店铺
|
5
|
+
invalid_shop_url: 商店域无效
|
6
|
+
enable_cookies_heading: 从 %{app} 启用 Cookie
|
7
|
+
enable_cookies_body: 您必须在此浏览器中手动启用 Cookie 才能在 Shopify 中使用 %{app}。
|
8
|
+
enable_cookies_footer: Cookie 使此应用能够通过暂时存储您的首选项和个人信息来验证您的身份。这些信息将在 30 天后过期。
|
9
|
+
enable_cookies_action: 启用 Cookie
|
10
|
+
top_level_interaction_heading: 您的浏览器需要对 %{app} 进行验证
|
11
|
+
top_level_interaction_body: 您的浏览器要求类似 %{app} 的第三方应用向您请求访问 Cookie,之后 Shopify 才能为您打开它。
|
12
|
+
top_level_interaction_action: 继续
|
13
|
+
request_storage_access_heading: "%{app} 需要访问 Cookie"
|
14
|
+
request_storage_access_body: 这使此应用能够通过暂时存储您的个人信息来验证您的身份。单击继续并启用 Cookie 以使用此应用。
|
15
|
+
request_storage_access_footer: Cookie 将在 30 天后过期。
|
16
|
+
request_storage_access_action: 继续
|
@@ -0,0 +1,17 @@
|
|
1
|
+
---
|
2
|
+
zh-TW:
|
3
|
+
logged_out: 登出成功
|
4
|
+
could_not_log_in: 無法登入 Shopify 商店
|
5
|
+
invalid_shop_url: 商店網域無效
|
6
|
+
enable_cookies_heading: 啟用 %{app} 的 Cookie
|
7
|
+
enable_cookies_body: 您必須在此瀏覽器中手動啟用 Cookie,才能夠在 Shopify 使用 %{app}。
|
8
|
+
enable_cookies_footer: Cookie 可讓應用程式暫時儲存您的偏好設定和個人資訊,藉此驗證您的身分,這些資料會在 30 天後失效。
|
9
|
+
enable_cookies_action: 啟用 Cookie
|
10
|
+
top_level_interaction_heading: 您的瀏覽器需要驗證 %{app}
|
11
|
+
top_level_interaction_body: 您的瀏覽器會要求第三方應用程式 (例如:%{app}) 向您請求 Cookie 的存取權限,然後才讓 Shopify
|
12
|
+
為您開啟此應用程式。
|
13
|
+
top_level_interaction_action: 繼續
|
14
|
+
request_storage_access_heading: "%{app} 需要 Cookie 存取權限"
|
15
|
+
request_storage_access_body: Cookie 可讓應用程式暫時儲存您的個人資訊,藉此驗證您的身分。按一下繼續並允許 Cookie 使用此應用程式。
|
16
|
+
request_storage_access_footer: Cookie 將於 30 天後失效。
|
17
|
+
request_storage_access_action: 繼續
|
data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb
CHANGED
@@ -12,7 +12,9 @@ module ShopifyApp
|
|
12
12
|
def init_after_authenticate_config
|
13
13
|
initializer = load_initializer
|
14
14
|
|
15
|
-
|
15
|
+
after_authenticate_job_config =
|
16
|
+
" config.after_authenticate_job = "\
|
17
|
+
"{ job: Shopify::AfterAuthenticateJob, inline: false }\n"
|
16
18
|
|
17
19
|
inject_into_file(
|
18
20
|
'config/initializers/shopify_app.rb',
|
@@ -9,6 +9,7 @@ module ShopifyApp
|
|
9
9
|
class_option :application_name, type: :array, default: ['My', 'Shopify', 'App']
|
10
10
|
class_option :api_key, type: :string, default: '<api_key>'
|
11
11
|
class_option :secret, type: :string, default: '<secret>'
|
12
|
+
class_option :old_secret, type: :string, default: '<old_secret>'
|
12
13
|
class_option :scope, type: :array, default: ['read_products']
|
13
14
|
class_option :embedded, type: :string, default: 'true'
|
14
15
|
|
@@ -16,6 +17,7 @@ module ShopifyApp
|
|
16
17
|
@application_name = format_array_argument(options['application_name'])
|
17
18
|
@api_key = options['api_key']
|
18
19
|
@secret = options['secret']
|
20
|
+
@old_secret = options['old_secret']
|
19
21
|
@scope = format_array_argument(options['scope'])
|
20
22
|
|
21
23
|
template 'shopify_app.rb', 'config/initializers/shopify_app.rb'
|
@@ -2,6 +2,7 @@ ShopifyApp.configure do |config|
|
|
2
2
|
config.application_name = "<%= @application_name %>"
|
3
3
|
config.api_key = "<%= @api_key %>"
|
4
4
|
config.secret = "<%= @secret %>"
|
5
|
+
config.old_secret = "<%= @old_secret %>"
|
5
6
|
config.scope = "<%= @scope %>" # Consult this page for more scope options:
|
6
7
|
# https://help.shopify.com/en/api/getting-started/authentication/oauth/scopes
|
7
8
|
config.embedded_app = <%= embedded_app? %>
|
@@ -1,16 +1,19 @@
|
|
1
|
-
|
2
|
-
ShopifyApp.configuration.api_key,
|
3
|
-
ShopifyApp.configuration.secret,
|
4
|
-
scope: ShopifyApp.configuration.scope,
|
5
|
-
setup: lambda { |env|
|
6
|
-
strategy = env['omniauth.strategy']
|
1
|
+
# frozen_string_literal: true
|
7
2
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
3
|
+
provider :shopify,
|
4
|
+
ShopifyApp.configuration.api_key,
|
5
|
+
ShopifyApp.configuration.secret,
|
6
|
+
scope: ShopifyApp.configuration.scope,
|
7
|
+
setup: lambda { |env|
|
8
|
+
strategy = env['omniauth.strategy']
|
14
9
|
|
15
|
-
|
16
|
-
|
10
|
+
shopify_auth_params = strategy.session['shopify.omniauth_params']&.with_indifferent_access
|
11
|
+
shop = if shopify_auth_params.present?
|
12
|
+
"https://#{shopify_auth_params[:shop]}"
|
13
|
+
else
|
14
|
+
''
|
15
|
+
end
|
16
|
+
|
17
|
+
strategy.options[:client_options][:site] = shop
|
18
|
+
strategy.options[:old_client_secret] = ShopifyApp.configuration.old_secret
|
19
|
+
}
|
data/lib/generators/shopify_app/rotate_shopify_token_job/rotate_shopify_token_job_generator.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/base'
|
4
|
+
|
5
|
+
module ShopifyApp
|
6
|
+
module Generators
|
7
|
+
class RotateShopifyTokenJobGenerator < Rails::Generators::Base
|
8
|
+
source_root File.expand_path('../templates', __FILE__)
|
9
|
+
|
10
|
+
def add_rotate_shopify_token_job
|
11
|
+
copy_file('rotate_shopify_token_job.rb', "app/jobs/shopify/rotate_shopify_token_job.rb")
|
12
|
+
copy_file('rotate_shopify_token.rake', "lib/tasks/shopify/rotate_shopify_token.rake")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
namespace :shopify do
|
3
|
+
desc "Rotate shopify tokens for all active shops"
|
4
|
+
task :rotate_shopify_tokens, [:refresh_token] => :environment do |_t, args|
|
5
|
+
all_active_shops.find_each do |shop|
|
6
|
+
Shopify::RotateShopifyTokenJob.perform_later(
|
7
|
+
shop_domain: shop.shopify_domain,
|
8
|
+
refresh_token: args[:refresh_token]
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Its implementation will depend on the app configuration. Change accordingly.
|
14
|
+
def all_active_shops
|
15
|
+
Shop.all
|
16
|
+
end
|
17
|
+
end
|
data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token_job.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shopify
|
4
|
+
class RotateShopifyTokenJob < ActiveJob::Base
|
5
|
+
def perform(params)
|
6
|
+
@shop = Shop.find_by(shopify_domain: params[:shop_domain])
|
7
|
+
return unless @shop
|
8
|
+
|
9
|
+
config = ShopifyApp.configuration
|
10
|
+
uri = URI("https://#{@shop.shopify_domain}/admin/oauth/access_token")
|
11
|
+
post_data = {
|
12
|
+
client_id: config.api_key,
|
13
|
+
client_secret: config.secret,
|
14
|
+
refresh_token: params[:refresh_token],
|
15
|
+
access_token: @shop.shopify_token,
|
16
|
+
}
|
17
|
+
|
18
|
+
@response = Net::HTTP.post_form(uri, post_data)
|
19
|
+
return log_error(response_expcetion_error_message) unless @response.is_a?(Net::HTTPSuccess)
|
20
|
+
|
21
|
+
access_token = JSON.parse(@response.body)['access_token']
|
22
|
+
return log_error(no_access_token_error_message) unless access_token
|
23
|
+
|
24
|
+
@shop.update(shopify_token: access_token)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def log_error(message)
|
30
|
+
Rails.logger.error(message)
|
31
|
+
end
|
32
|
+
|
33
|
+
def no_access_token_error_message
|
34
|
+
"RotateShopifyTokenJob response returned no access token for shop: #{@shop.shopify_domain}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def response_exception_error_message
|
38
|
+
"RotateShopifyTokenJob failed for shop: #{@shop.shopify_domain}." \
|
39
|
+
"Response returned status: #{@response.code}. Error message: #{@response.message}. "
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -15,12 +15,16 @@ module ShopifyApp
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def hmac_valid?(data)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
secrets = [ShopifyApp.configuration.secret, ShopifyApp.configuration.old_secret].reject(&:blank?)
|
19
|
+
|
20
|
+
secrets.any? do |secret|
|
21
|
+
digest = OpenSSL::Digest.new('sha256')
|
22
|
+
|
23
|
+
ActiveSupport::SecurityUtils.secure_compare(
|
24
|
+
shopify_hmac,
|
25
|
+
Base64.strict_encode64(OpenSSL::HMAC.digest(digest, secret, data))
|
26
|
+
)
|
27
|
+
end
|
24
28
|
end
|
25
29
|
|
26
30
|
def shop_domain
|
data/lib/shopify_app/version.rb
CHANGED
data/shopify_app.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.add_runtime_dependency('browser_sniffer', '~> 1.1.0')
|
14
14
|
s.add_runtime_dependency('rails', '>= 5.0.0')
|
15
15
|
s.add_runtime_dependency('shopify_api', '>= 4.3.5')
|
16
|
-
s.add_runtime_dependency('omniauth-shopify-oauth2', '~> 2.
|
16
|
+
s.add_runtime_dependency('omniauth-shopify-oauth2', '~> 2.1.0')
|
17
17
|
|
18
18
|
s.add_development_dependency('rake')
|
19
19
|
s.add_development_dependency('byebug')
|
data/translation.yml
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shopify_app
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.
|
4
|
+
version: 8.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-02-
|
11
|
+
date: 2019-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: browser_sniffer
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 2.
|
61
|
+
version: 2.1.0
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 2.
|
68
|
+
version: 2.1.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -186,7 +186,10 @@ files:
|
|
186
186
|
- config/locales/fr.yml
|
187
187
|
- config/locales/it.yml
|
188
188
|
- config/locales/ja.yml
|
189
|
+
- config/locales/nl.yml
|
189
190
|
- config/locales/pt-BR.yml
|
191
|
+
- config/locales/zh-CN.yml
|
192
|
+
- config/locales/zh-TW.yml
|
190
193
|
- config/routes.rb
|
191
194
|
- docs/Quickstart.md
|
192
195
|
- docs/Releasing.md
|
@@ -212,6 +215,9 @@ files:
|
|
212
215
|
- lib/generators/shopify_app/install/templates/omniauth.rb
|
213
216
|
- lib/generators/shopify_app/install/templates/shopify_app.rb
|
214
217
|
- lib/generators/shopify_app/install/templates/shopify_provider.rb
|
218
|
+
- lib/generators/shopify_app/rotate_shopify_token_job/rotate_shopify_token_job_generator.rb
|
219
|
+
- lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token.rake
|
220
|
+
- lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token_job.rb
|
215
221
|
- lib/generators/shopify_app/routes/routes_generator.rb
|
216
222
|
- lib/generators/shopify_app/routes/templates/routes.rb
|
217
223
|
- lib/generators/shopify_app/shop_model/shop_model_generator.rb
|