shopify_app 22.2.1 → 22.3.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.nvmrc +1 -1
  3. data/CHANGELOG.md +15 -1
  4. data/CONTRIBUTING.md +0 -5
  5. data/Gemfile.lock +75 -71
  6. data/README.md +8 -1
  7. data/app/assets/javascripts/shopify_app/redirect.js +3 -9
  8. data/app/controllers/shopify_app/sessions_controller.rb +2 -1
  9. data/app/views/shopify_app/shared/redirect.html.erb +5 -1
  10. data/config/locales/cs.yml +0 -18
  11. data/config/locales/da.yml +0 -15
  12. data/config/locales/de.yml +0 -17
  13. data/config/locales/en.yml +0 -11
  14. data/config/locales/es.yml +0 -17
  15. data/config/locales/fi.yml +0 -15
  16. data/config/locales/fr.yml +0 -18
  17. data/config/locales/it.yml +0 -16
  18. data/config/locales/ja.yml +0 -12
  19. data/config/locales/ko.yml +0 -14
  20. data/config/locales/nb.yml +0 -16
  21. data/config/locales/nl.yml +0 -16
  22. data/config/locales/pl.yml +0 -16
  23. data/config/locales/pt-BR.yml +0 -16
  24. data/config/locales/pt-PT.yml +0 -17
  25. data/config/locales/sv.yml +0 -16
  26. data/config/locales/th.yml +0 -15
  27. data/config/locales/tr.yml +0 -17
  28. data/config/locales/vi.yml +0 -17
  29. data/config/locales/zh-CN.yml +0 -11
  30. data/config/locales/zh-TW.yml +0 -11
  31. data/docs/Upgrading.md +17 -3
  32. data/docs/shopify_app/sessions.md +4 -1
  33. data/karma.conf.js +0 -3
  34. data/lib/generators/shopify_app/install/templates/shopify_app.rb.tt +2 -2
  35. data/lib/shopify_app/configuration.rb +6 -4
  36. data/lib/shopify_app/controller_concerns/csrf_protection.rb +2 -1
  37. data/lib/shopify_app/controller_concerns/embedded_app.rb +5 -1
  38. data/lib/shopify_app/controller_concerns/localization.rb +1 -1
  39. data/lib/shopify_app/controller_concerns/login_protection.rb +8 -1
  40. data/lib/shopify_app/controller_concerns/token_exchange.rb +12 -8
  41. data/lib/shopify_app/controller_concerns/with_shopify_id_token.rb +16 -9
  42. data/lib/shopify_app/engine.rb +4 -9
  43. data/lib/shopify_app/utils.rb +10 -1
  44. data/lib/shopify_app/version.rb +1 -1
  45. data/package.json +1 -1
  46. data/shopify_app.gemspec +2 -1
  47. data/yarn.lock +8 -8
  48. metadata +23 -26
  49. data/app/assets/images/storage_access.svg +0 -1
  50. data/app/assets/javascripts/shopify_app/app_bridge_3.7.8.js +0 -10
  51. data/app/assets/javascripts/shopify_app/app_bridge_redirect.js +0 -22
@@ -3,19 +3,3 @@ pl:
3
3
  logged_out: Pomyślne wylogowanie
4
4
  could_not_log_in: Nie można zalogować się do sklepu Shopify
5
5
  invalid_shop_url: Nieprawidłowa domena sklepu
6
- enable_cookies_heading: Włącz korzystanie z plików cookie z %{app}
7
- enable_cookies_body: Aby móc korzystać z %{app} w Shopify, musisz ręcznie włączyć
8
- korzystanie z plików cookie w tej przeglądarce.
9
- enable_cookies_footer: Pliki cookie umożliwiają uwierzytelnianie aplikacji przez
10
- tymczasowe przechowywanie preferencji i danych osobowych. Wygasają one po 30 dniach.
11
- enable_cookies_action: Włącz korzystanie z plików cookie
12
- top_level_interaction_heading: Twoja przeglądarka wymaga uwierzytelnienia %{app}
13
- top_level_interaction_body: Twoja przeglądarka wymaga takich aplikacji jak %{app},
14
- aby poprosić o dostęp do plików cookie, zanim Shopify będzie mógł ją otworzyć.
15
- top_level_interaction_action: Kontynuuj
16
- request_storage_access_heading: "%{app} potrzebuje dostępu do plików cookie"
17
- request_storage_access_body: Dzięki temu aplikacja może Cię uwierzytelniać, tymczasowo,
18
- przechowując Twoje dane osobowe. Kliknij przycisk Kontynuuj i zezwalaj na pliki
19
- cookie, aby korzystać z aplikacji.
20
- request_storage_access_footer: Pliki cookie wygasają po 30 dniach.
21
- request_storage_access_action: Kontynuuj
@@ -3,19 +3,3 @@ pt-BR:
3
3
  logged_out: Você saiu.
4
4
  could_not_log_in: Não foi possível fazer login na Shopify store
5
5
  invalid_shop_url: Domínio de loja inválido
6
- enable_cookies_heading: Habilitar cookies de %{app}
7
- enable_cookies_body: Você precisa habilitar manualmente os cookies neste navegador
8
- para usar %{app} dentro da Shopify.
9
- enable_cookies_footer: Os cookies permitem que o app o autentique armazenando temporariamente
10
- suas preferências e dados pessoais. Eles expiram depois de 30 dias.
11
- enable_cookies_action: Habilitar cookies
12
- top_level_interaction_heading: Seu navegador precisa autenticar %{app}
13
- top_level_interaction_body: Seu navegador exige que apps como o %{app} consultem
14
- você sobre o acesso a cookies antes que a Shopify os abra.
15
- top_level_interaction_action: Continuar
16
- request_storage_access_heading: "%{app} precisa acessar cookies"
17
- request_storage_access_body: Isso permite que o app autentique você armazenando
18
- temporariamente seus dados pessoais. Clique em continuar e permita os cookies
19
- para usar o app.
20
- request_storage_access_footer: Os cookies expiram depois de 30 dias.
21
- request_storage_access_action: Continuar
@@ -3,20 +3,3 @@ pt-PT:
3
3
  logged_out: Terminou a sessão com sucesso
4
4
  could_not_log_in: Não foi possível iniciar sessão na loja da Shopify
5
5
  invalid_shop_url: Domínio de loja inválido
6
- enable_cookies_heading: Ativar cookies de %{app}
7
- enable_cookies_body: Tem de ativar manualmente os cookies neste navegador para utilizar
8
- %{app} dentro da Shopify.
9
- enable_cookies_footer: Os cookies permitem que a aplicação o autentique armazenando
10
- temporariamente as suas preferências e informações pessoais. Expiram ao fim de
11
- 30 dias.
12
- enable_cookies_action: Ativar cookies
13
- top_level_interaction_heading: O seu navegador tem de autenticar %{app}
14
- top_level_interaction_body: O seu navegador exige que aplicações como %{app} lhe
15
- solicitem o acesso de cookies, antes que a Shopify as possa abrir.
16
- top_level_interaction_action: Continuar
17
- request_storage_access_heading: "%{app} tem de aceder a cookies"
18
- request_storage_access_body: Isto permite que a aplicação o autentique armazenando
19
- temporariamente as suas informações pessoais. Clique em continuar e permita os
20
- cookies para utilizar a aplicação.
21
- request_storage_access_footer: Os cookies expiram ao fim de 30 dias.
22
- request_storage_access_action: Continuar
@@ -3,19 +3,3 @@ sv:
3
3
  logged_out: Har loggats ut
4
4
  could_not_log_in: Det gick inte att logga in i Shopify-butiken
5
5
  invalid_shop_url: Ogiltig butiksdomän
6
- enable_cookies_heading: Aktivera cookies från %{app}
7
- enable_cookies_body: Du måste aktivera cookies manuellt i den här webbläsaren för
8
- att kunna använda %{app} inom Shopify.
9
- enable_cookies_footer: Cookies låter appen autentisera dig genom att tillfälligt
10
- lagra dina inställningar och personuppgifter. De upphör efter 30 dagar.
11
- enable_cookies_action: Aktivera cookies
12
- top_level_interaction_heading: Din webbläsare måste verifiera %{app}
13
- top_level_interaction_body: Din webbläsare kräver att appar som %{app} frågar dig
14
- om tillgång till cookies innan Shopify kan öppna den för dig.
15
- top_level_interaction_action: Fortsätt
16
- request_storage_access_heading: "%{app} behöver tillgång till cookies"
17
- request_storage_access_body: Detta gör det möjligt för appen att autentisera dig
18
- genom att tillfälligt lagra din personliga information. Klicka på fortsätt och
19
- tillåta cookies att använda appen.
20
- request_storage_access_footer: Cookies upphör efter 30 dagar.
21
- request_storage_access_action: Fortsätt
@@ -3,18 +3,3 @@ th:
3
3
  logged_out: ออกจากระบบสำเร็จ
4
4
  could_not_log_in: ไม่สามารถเข้าสู่ระบบร้านค้า Shopify ได้
5
5
  invalid_shop_url: โดเมนร้านค้าไม่ถูกต้อง
6
- enable_cookies_heading: เปิดใช้คุกกี้จาก %{app}
7
- enable_cookies_body: คุณต้องเปิดใช้คุกกี้ด้วยตนเองในเบราว์เซอร์นี้เพื่อใช้งาน %{app}
8
- ภายใน Shopify
9
- enable_cookies_footer: คุกกี้ช่วยให้แอปตรวจสอบความถูกต้องของคุณด้วยการจัดเก็บความชื่นชอบและข้อมูลส่วนตัวของคุณชั่วคราว
10
- คุกกี้จะหมดอายุหลังจาก 30 วัน
11
- enable_cookies_action: เปิดใช้คุกกี้
12
- top_level_interaction_heading: เบราว์เซอร์ของคุณต้องรับรองความถูกต้องของ %{app}
13
- top_level_interaction_body: เบราว์เซอร์ของคุณต้องการแอปอย่าง %{app} เพื่อขอให้คุณเข้าถึงคุกกี้ก่อนที่
14
- Shopify จะสามารถเปิดมันให้คุณได้
15
- top_level_interaction_action: ดำเนินการต่อ
16
- request_storage_access_heading: "%{app} ต้องการสิทธิ์การเข้าถึงคุกกี้"
17
- request_storage_access_body: สิ่งนี้ช่วยให้แอปตรวจสอบความถูกต้องของคุณด้วยการจัดเก็บข้อมูลส่วนตัวของคุณชั่วคราว
18
- คลิกดำเนินการต่อและอนุญาตให้คุกกี้ใช้แอป
19
- request_storage_access_footer: คุกกี้จะหมดอายุหลังจาก 30 วัน
20
- request_storage_access_action: ดำเนินการต่อ
@@ -3,20 +3,3 @@ tr:
3
3
  logged_out: Oturum başarıyla kapatıldı
4
4
  could_not_log_in: Shopify mağazasında oturum açılamadı
5
5
  invalid_shop_url: Geçersiz mağaza alan adı
6
- enable_cookies_heading: "%{app} uygulamasından çerezleri etkinleştir"
7
- enable_cookies_body: "%{app} uygulamasını Shopify içinde kullanabilmek için bu tarayıcıda
8
- çerezleri manuel olarak etkinleştirmelisiniz."
9
- enable_cookies_footer: Çerezler, tercihlerinizi ve kişisel bilgilerinizi geçici
10
- olarak saklayıp uygulamanın kimliğinizi doğrulamasına imkan tanır. Çerezlerin
11
- süresi 30 gün sonra sonra sona erer.
12
- enable_cookies_action: Çerezleri etkinleştir
13
- top_level_interaction_heading: Tarayıcınızın %{app} kimliğini doğrulaması gerekiyor
14
- top_level_interaction_body: Tarayıcınız, Shopify tarafından açılmadan önce %{app}
15
- gibi uygulamaların sizden çerezlere erişim izni istemesini zorunlu tutuyor.
16
- top_level_interaction_action: Devam
17
- request_storage_access_heading: "%{app} uygulamasının çerezlere erişmesi gerekiyor"
18
- request_storage_access_body: Böylece uygulama, kişisel bilgilerinizi geçici olarak
19
- saklayıp kimliğinizi doğrulayabilir. Devam et'e tıklayın ve çerezlerin uygulamayı
20
- kullanmasına izin verin.
21
- request_storage_access_footer: Çerezlerin süresi 30 gün sonra sonra sona erer.
22
- request_storage_access_action: Devam
@@ -3,20 +3,3 @@ vi:
3
3
  logged_out: Đã đăng xuất thành công
4
4
  could_not_log_in: Không thể đăng nhập vào cửa hàng trên Shopify
5
5
  invalid_shop_url: Miền cửa hàng không hợp lệ
6
- enable_cookies_heading: Bật cookie từ %{app}
7
- enable_cookies_body: Bạn phải bật cookie trong trình duyệt này theo cách thủ công
8
- để sử dụng %{app} trong Shopify.
9
- enable_cookies_footer: Cookie cho phép ứng dụng xác thực bạn bằng cách tạm thời
10
- lưu trữ tùy chọn và thông tin cá nhân của bạn. Những thông tin này sẽ hết hạn
11
- sau 30 ngày.
12
- enable_cookies_action: Bật cookie
13
- top_level_interaction_heading: Trình duyệt của bạn cần xác thực %{app}
14
- top_level_interaction_body: Trình duyệt của bạn cần các ứng dụng như %{app} để yêu
15
- cầu quyền truy cập vào cookie thì Shopify mới có thể mở giúp bạn.
16
- top_level_interaction_action: Tiếp tục
17
- request_storage_access_heading: "%{app} cần quyền truy cập cookie"
18
- request_storage_access_body: Nhờ vậy, ứng dụng có thể xác thực bạn bằng cách tạm
19
- thời lưu trữ thông tin cá nhân của bạn. Nhấp vào tiếp tục và cho phép cookie sử
20
- dụng ứng dụng.
21
- request_storage_access_footer: Cookie sẽ hết hạn sau 30 ngày.
22
- request_storage_access_action: Tiếp tục
@@ -3,14 +3,3 @@ zh-CN:
3
3
  logged_out: 已成功退出
4
4
  could_not_log_in: 无法登录到 Shopify 商店
5
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: 继续
@@ -3,14 +3,3 @@ zh-TW:
3
3
  logged_out: 登出成功
4
4
  could_not_log_in: 無法登入 Shopify 商店
5
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 可讓應用程式暫時儲存您的個人資訊,藉此驗證您的身分。按一下繼續並允許 Cookie 使用此應用程式。
15
- request_storage_access_footer: Cookie 將於 30 天後失效。
16
- request_storage_access_action: 繼續
data/docs/Upgrading.md CHANGED
@@ -43,6 +43,7 @@ We also recommend the use of a staging site which matches your production enviro
43
43
  If you do run into issues, we recommend looking at our [debugging tips.](https://github.com/Shopify/shopify_app/blob/main/docs/Troubleshooting.md#debugging-tips)
44
44
 
45
45
  ## Unreleased
46
+
46
47
  #### (v23.0.0) - Deprecated methods in CallbackController
47
48
  The following methods from `ShopifyApp::CallbackController` have been deprecated in `v23.0.0`
48
49
  - `perform_after_authenticate_job`
@@ -53,17 +54,30 @@ If you have overwritten these methods in your callback controller to modify the
53
54
  update your app to use configurable option `config.custom_post_authenticate_tasks` instead. See [post authenticate tasks](/docs/shopify_app/authentication.md#post-authenticate-tasks)
54
55
  for more information.
55
56
 
57
+ #### (v23.0.0) - Removed `ShopifyApp::JWTMiddleware`
58
+ The `ShopifyApp::JWTMiddleware` middleware has been removed in `v23.0.0`. This middleware was used to populate the following environment variables from the JWT session token:
59
+ - `request.env["jwt.token"]`
60
+ - `request.env["jwt.shopify_domain"]`
61
+ - `request.env["jwt.shopify_user_id"]`
62
+ - `request.env["jwt.expire_at"]`
63
+
64
+ If you are using any of these variables in your app, you'll need to replace them. You can instead include the `ShopifyApp::WithShopifyIdToken` concern, which does the same JWT parsing as the middleware, and exposes the same values in the following helper methods:
65
+ - `shopify_id_token`
66
+ - `jwt_shopify_domain`
67
+ - `jwt_shopify_user_id`
68
+ - `jwt_expire_at`
69
+
56
70
  #### (v23.0.0) - Deprecated "ShopifyApp::JWT" class
57
71
  The `ShopifyApp::JWT` class has been deprecated in `v23.0.0`. Use [ShopifyAPI::Auth::JwtPayload](https://github.com/Shopify/shopify-api-ruby/blob/main/lib/shopify_api/auth/jwt_payload.rb)
58
72
  class from the `shopify_api` gem instead. A search and replace should be enough for this migration.
59
- - `ShopifyAPI::Auth::JwtPayload` is a superset of the `ShopifyApp::JWT` class, and contains methods that were available in `ShopifyApp::JWT`.
73
+ - `ShopifyAPI::Auth::JwtPayload` is a superset of the `ShopifyApp::JWT` class, and contains methods that were available in `ShopifyApp::JWT`.
60
74
  - `ShopifyAPI::Auth::JwtPayload` raises `ShopifyAPI::Errors::InvalidJwtTokenError` if the token is invalid.
61
75
 
62
76
  ## Upgrading to `v22.2.0`
63
77
  #### Added new feature for zero redirect embedded app authorization flow - Token Exchange
64
- A new embedded app authorization strategy has been introduced in `v22.2.0` that eliminates the redirects that were previously necessary for OAuth.
78
+ A new embedded app authorization strategy has been introduced in `v22.2.0` that eliminates the redirects that were previously necessary for OAuth.
65
79
  It can replace the existing installation and authorization code grant flow.
66
- See [new embedded app authorization strategy](./README.md#new-embedded-app-authorization-strategy) for more information.
80
+ See [new embedded app authorization strategy](/README.md#new-embedded-app-authorization-strategy-token-exchange) for more information.
67
81
 
68
82
  ## Upgrading to `v22.0.0`
69
83
  #### Dropped support for Ruby 2.x
@@ -59,7 +59,10 @@ If your app has user interactions and would like to control permission based on
59
59
 
60
60
  [Shop (offline) tokens must still be maintained](#shop-offline-token-storage).
61
61
 
62
- 1. Run the following generator to create a user model to store the individual based access tokens
62
+ 1. Run the following generator to create a user model to store the individual based access tokens.
63
+
64
+ ⚠️ If you started from the [Ruby App Template](https://github.com/Shopify/shopify-app-template-ruby), you don't need to run the generator as it's already included in the template. You can skip this step.
65
+
63
66
  ```sh
64
67
  rails generate shopify_app:user_model
65
68
  ```
data/karma.conf.js CHANGED
@@ -16,9 +16,6 @@ module.exports = function(config) {
16
16
  exclude: [
17
17
  // Exclude JS files that create 'DOMContentLoaded' event listeners
18
18
  'app/assets/javascripts/**/redirect.js',
19
- 'app/assets/javascripts/**/storage_access_redirect.js',
20
- 'app/assets/javascripts/**/top_level_interaction.js',
21
- 'app/assets/javascripts/**/partition_cookies.js',
22
19
  ],
23
20
  mochaReporter: {
24
21
  output: 'autowatch',
@@ -32,8 +32,8 @@ ShopifyApp.configure do |config|
32
32
  # amount: 5,
33
33
  # interval: ShopifyApp::BillingConfiguration::INTERVAL_EVERY_30_DAYS,
34
34
  # currency_code: "USD", # Only supports USD for now
35
- # trial_days: 0
36
- # test: ENV.fetch('SHOPIFY_TEST_CHARGES', !Rails.env.production?)
35
+ # trial_days: 0,
36
+ # test: !ENV['SHOPIFY_TEST_CHARGES'].nil? ? ["true", "1"].include?(ENV['SHOPIFY_TEST_CHARGES']) : !Rails.env.production?
37
37
  # )
38
38
 
39
39
  if defined? Rails::Server
@@ -58,7 +58,7 @@ module ShopifyApp
58
58
  @webhooks_manager_queue_name = Rails.application.config.active_job.queue_name
59
59
  @disable_webpacker = ENV["SHOPIFY_APP_DISABLE_WEBPACKER"].present?
60
60
 
61
- log_callback_controller_method_deprecation
61
+ log_v23_deprecations
62
62
  end
63
63
 
64
64
  def login_url
@@ -163,16 +163,18 @@ module ShopifyApp
163
163
 
164
164
  private
165
165
 
166
- def log_callback_controller_method_deprecation
166
+ def log_v23_deprecations
167
167
  return unless Rails.env.development?
168
168
 
169
169
  # TODO: Remove this before releasing v23.0.0
170
170
  message = <<~EOS
171
171
  ================================================
172
- => Upcoming deprecation in v23.0:
172
+ => Upcoming changes in v23.0:
173
173
  * 'CallbackController::perform_after_authenticate_job' and related methods 'install_webhooks', 'perform_after_authenticate_job'
174
- * will be deprecated from CallbackController in the next major release. If you need to customize
174
+ * are deprecated and will be removed from CallbackController in the next major release. If you need to customize
175
175
  * post authentication tasks, see https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/authentication.md#post-authenticate-tasks
176
+
177
+ * ShopifyApp::JWTMiddleware will be removed, use ShopifyApp::WithShopifyIdToken instead.
176
178
  ================================================
177
179
  EOS
178
180
  puts message
@@ -4,13 +4,14 @@ module ShopifyApp
4
4
  module CsrfProtection
5
5
  extend ActiveSupport::Concern
6
6
  included do
7
+ include ShopifyApp::WithShopifyIdToken
7
8
  protect_from_forgery with: :exception, unless: :valid_session_token?
8
9
  end
9
10
 
10
11
  private
11
12
 
12
13
  def valid_session_token?
13
- request.env["jwt.shopify_domain"]
14
+ jwt_payload.present?
14
15
  end
15
16
  end
16
17
  end
@@ -25,7 +25,11 @@ module ShopifyApp
25
25
  return redirect_to(ShopifyApp.configuration.login_url)
26
26
  end
27
27
 
28
- redirect_path = ShopifyAPI::Auth.embedded_app_url(host)
28
+ original_path = request.path
29
+ original_params = request.query_parameters.except(:host, :shop, :id_token)
30
+ original_path += "?#{original_params.to_query}" if original_params.present?
31
+
32
+ redirect_path = ShopifyAPI::Auth.embedded_app_url(host) + original_path.to_s
29
33
  redirect_path = ShopifyApp.configuration.root_url if deduced_phishing_attack?(redirect_path)
30
34
  redirect_to(redirect_path, allow_other_host: true)
31
35
  end
@@ -11,7 +11,7 @@ module ShopifyApp
11
11
  private
12
12
 
13
13
  def set_locale(&action)
14
- locale = params[:locale] || I18n.default_locale
14
+ locale = params[:locale] || session[:locale] || I18n.default_locale
15
15
 
16
16
  # Fallback to the 2 letter language code if the requested locale unavailable
17
17
  unless I18n.available_locales.include?(locale.to_sym)
@@ -122,12 +122,19 @@ module ShopifyApp
122
122
  query = Rack::Utils.parse_nested_query(referer.query)
123
123
  query = query.merge(sanitized_params).to_query
124
124
  end
125
- session[:return_to] = query.blank? ? path.to_s : "#{path}?#{query}"
125
+ session[:return_to] = return_to_url(path, query)
126
126
  ShopifyApp::Logger.debug("Redirecting to #{login_url_with_optional_shop}")
127
127
  redirect_to(login_url_with_optional_shop)
128
128
  end
129
129
  end
130
130
 
131
+ # Apps which use cookies for session storage, and thus have a 4kB session data
132
+ # limit, may choose to override this method to prevent excessively-long `query`
133
+ # strings from causing a CookieOverflow error.
134
+ def return_to_url(path, query)
135
+ query.blank? ? path.to_s : "#{path}?#{query}"
136
+ end
137
+
131
138
  def close_session
132
139
  ShopifyApp::Logger.debug("Closing session")
133
140
  clear_shopify_session
@@ -23,8 +23,7 @@ module ShopifyApp
23
23
  ShopifyAPI::Context.activate_session(current_shopify_session)
24
24
  with_token_refetch(current_shopify_session, shopify_id_token, &block)
25
25
  rescue *INVALID_SHOPIFY_ID_TOKEN_ERRORS => e
26
- ShopifyApp::Logger.debug("Responding to invalid Shopify ID token: #{e.message}")
27
- respond_to_invalid_shopify_id_token unless performed?
26
+ respond_to_invalid_shopify_id_token(e)
28
27
  ensure
29
28
  ShopifyApp::Logger.debug("Deactivating session")
30
29
  ShopifyAPI::Context.deactivate_session
@@ -49,6 +48,8 @@ module ShopifyApp
49
48
 
50
49
  def current_shopify_domain
51
50
  sanitized_shop_name || current_shopify_session&.shop
51
+ rescue *INVALID_SHOPIFY_ID_TOKEN_ERRORS => e
52
+ respond_to_invalid_shopify_id_token(e)
52
53
  end
53
54
 
54
55
  private
@@ -58,12 +59,15 @@ module ShopifyApp
58
59
  ShopifyApp::Auth::TokenExchange.perform(shopify_id_token)
59
60
  end
60
61
 
61
- def respond_to_invalid_shopify_id_token
62
+ def respond_to_invalid_shopify_id_token(error)
63
+ ShopifyApp::Logger.debug("Responding to invalid Shopify ID token: #{error.message}")
64
+ return if performed?
65
+
62
66
  if request.headers["HTTP_AUTHORIZATION"].blank?
63
- if missing_embedded_param?
64
- redirect_to_embed_app_in_admin
65
- else
67
+ if embedded?
66
68
  redirect_to_bounce_page
69
+ else
70
+ redirect_to_embed_app_in_admin
67
71
  end
68
72
  else
69
73
  ShopifyApp::Logger.debug("Responding to invalid Shopify ID token with unauthorized response")
@@ -90,8 +94,8 @@ module ShopifyApp
90
94
  )
91
95
  end
92
96
 
93
- def missing_embedded_param?
94
- !params[:embedded].present? || params[:embedded] != "1"
97
+ def embedded?
98
+ params[:embedded] == "1" || request.env["HTTP_SEC_FETCH_DEST"] == "iframe"
95
99
  end
96
100
 
97
101
  def online_token_configured?
@@ -5,19 +5,31 @@ module ShopifyApp
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  def shopify_id_token
8
- @shopify_id_token ||= id_token_from_request_env || id_token_from_authorization_header || id_token_from_url_param
8
+ return @shopify_id_token if defined?(@shopify_id_token)
9
+
10
+ @shopify_id_token = id_token_from_authorization_header || id_token_from_url_param
11
+ end
12
+
13
+ def jwt_payload
14
+ return @jwt_payload if defined?(@jwt_payload)
15
+
16
+ @jwt_payload = shopify_id_token.present? ? ShopifyAPI::Auth::JwtPayload.new(shopify_id_token) : nil
9
17
  end
10
18
 
11
19
  def jwt_shopify_domain
12
- request.env["jwt.shopify_domain"]
20
+ return @jwt_shopify_domain if defined?(@jwt_shopify_domain)
21
+
22
+ @jwt_shopify_domain = if jwt_payload.present?
23
+ ShopifyApp::Utils.sanitize_shop_domain(jwt_payload.shopify_domain)
24
+ end
13
25
  end
14
26
 
15
27
  def jwt_shopify_user_id
16
- request.env["jwt.shopify_user_id"]
28
+ jwt_payload&.shopify_user_id
17
29
  end
18
30
 
19
31
  def jwt_expire_at
20
- expire_at = request.env["jwt.expire_at"]
32
+ expire_at = jwt_payload&.expire_at
21
33
  return unless expire_at
22
34
 
23
35
  expire_at - 5.seconds # 5s gap to start fetching new token in advance
@@ -25,11 +37,6 @@ module ShopifyApp
25
37
 
26
38
  private
27
39
 
28
- def id_token_from_request_env
29
- # This is set from ShopifyApp::JWTMiddleware
30
- request.env["jwt.token"]
31
- end
32
-
33
40
  def id_token_from_authorization_header
34
41
  request.headers["HTTP_AUTHORIZATION"]&.match(/^Bearer (.+)$/)&.[](1)
35
42
  end
@@ -16,21 +16,16 @@ module ShopifyApp
16
16
  engine_name "shopify_app"
17
17
  isolate_namespace ShopifyApp
18
18
 
19
+ initializer "shopify_app.middleware" do |app|
20
+ app.config.middleware.insert_after(::Rack::Runtime, ShopifyApp::JWTMiddleware)
21
+ end
22
+
19
23
  initializer "shopify_app.assets.precompile" do |app|
20
24
  app.config.assets.precompile += [
21
25
  "shopify_app/redirect.js",
22
- "shopify_app/post_redirect.js",
23
- "shopify_app/top_level.js",
24
- "shopify_app/enable_cookies.js",
25
- "shopify_app/request_storage_access.js",
26
- "storage_access.svg",
27
26
  ]
28
27
  end
29
28
 
30
- initializer "shopify_app.middleware" do |app|
31
- app.config.middleware.insert_after(::Rack::Runtime, ShopifyApp::JWTMiddleware)
32
- end
33
-
34
29
  initializer "shopify_app.redact_job_params" do
35
30
  ActiveSupport.on_load(:active_job) do
36
31
  if ActiveJob::Base.respond_to?(:log_arguments?)
@@ -12,7 +12,7 @@ module ShopifyApp
12
12
 
13
13
  def sanitize_shop_domain(shop_domain)
14
14
  uri = uri_from_shop_domain(shop_domain)
15
- return nil if uri.nil?
15
+ return nil if uri.nil? || uri.host.nil?
16
16
 
17
17
  trusted_domains.each do |trusted_domain|
18
18
  no_shop_name_in_subdomain = uri.host == trusted_domain
@@ -39,6 +39,15 @@ module ShopifyApp
39
39
  url.to_s
40
40
  end
41
41
 
42
+ def unified_admin_path(shop)
43
+ spin_env = ENV.fetch("SPIN_FQDN", nil)
44
+ if spin_env
45
+ "https://admin.web.#{spin_env}/store/#{shop}"
46
+ else
47
+ "https://admin.shopify.com/store/#{shop}"
48
+ end
49
+ end
50
+
42
51
  private
43
52
 
44
53
  def myshopify_domain
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShopifyApp
4
- VERSION = "22.2.1"
4
+ VERSION = "22.3.0"
5
5
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shopify_app",
3
- "version": "22.2.1",
3
+ "version": "22.3.0",
4
4
  "repository": "git@github.com:Shopify/shopify_app.git",
5
5
  "author": "Shopify",
6
6
  "license": "MIT",
data/shopify_app.gemspec CHANGED
@@ -16,11 +16,12 @@ Gem::Specification.new do |s|
16
16
 
17
17
  s.add_runtime_dependency("activeresource") # TODO: Remove this once all active resource dependencies are removed
18
18
  s.add_runtime_dependency("addressable", "~> 2.7")
19
- s.add_runtime_dependency("jwt", ">= 2.2.3")
20
19
  s.add_runtime_dependency("rails", "> 5.2.1")
21
20
  s.add_runtime_dependency("redirect_safely", "~> 1.0")
22
21
  s.add_runtime_dependency("shopify_api", ">= 14.3.0", "< 15.0")
23
22
  s.add_runtime_dependency("sprockets-rails", ">= 2.0.0")
23
+ # Deprecated: move to development dependencies when releasing v23
24
+ s.add_runtime_dependency("jwt", ">= 2.2.3")
24
25
 
25
26
  s.add_development_dependency("byebug")
26
27
  s.add_development_dependency("minitest")
data/yarn.lock CHANGED
@@ -1549,11 +1549,11 @@ brace-expansion@^2.0.1:
1549
1549
  balanced-match "^1.0.0"
1550
1550
 
1551
1551
  braces@^3.0.2, braces@~3.0.2:
1552
- version "3.0.2"
1553
- resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
1554
- integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
1552
+ version "3.0.3"
1553
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
1554
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
1555
1555
  dependencies:
1556
- fill-range "^7.0.1"
1556
+ fill-range "^7.1.1"
1557
1557
 
1558
1558
  browser-stdout@1.3.1:
1559
1559
  version "1.3.1"
@@ -1984,10 +1984,10 @@ fast-levenshtein@^2.0.6:
1984
1984
  resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
1985
1985
  integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
1986
1986
 
1987
- fill-range@^7.0.1:
1988
- version "7.0.1"
1989
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
1990
- integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
1987
+ fill-range@^7.1.1:
1988
+ version "7.1.1"
1989
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
1990
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
1991
1991
  dependencies:
1992
1992
  to-regex-range "^5.0.1"
1993
1993