shopify_app 22.2.0 → 22.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.nvmrc +1 -1
- data/CHANGELOG.md +18 -1
- data/CONTRIBUTING.md +0 -5
- data/Gemfile.lock +75 -71
- data/README.md +8 -1
- data/app/assets/javascripts/shopify_app/redirect.js +3 -9
- data/app/controllers/shopify_app/sessions_controller.rb +2 -1
- data/app/views/shopify_app/shared/redirect.html.erb +5 -1
- data/config/locales/cs.yml +0 -18
- data/config/locales/da.yml +0 -15
- data/config/locales/de.yml +0 -17
- data/config/locales/en.yml +0 -11
- data/config/locales/es.yml +0 -17
- data/config/locales/fi.yml +0 -15
- data/config/locales/fr.yml +0 -18
- data/config/locales/it.yml +0 -16
- data/config/locales/ja.yml +0 -12
- data/config/locales/ko.yml +0 -14
- data/config/locales/nb.yml +0 -16
- data/config/locales/nl.yml +0 -16
- data/config/locales/pl.yml +0 -16
- data/config/locales/pt-BR.yml +0 -16
- data/config/locales/pt-PT.yml +0 -17
- data/config/locales/sv.yml +0 -16
- data/config/locales/th.yml +0 -15
- data/config/locales/tr.yml +0 -17
- data/config/locales/vi.yml +0 -17
- data/config/locales/zh-CN.yml +0 -11
- data/config/locales/zh-TW.yml +0 -11
- data/docs/Upgrading.md +17 -3
- data/docs/shopify_app/sessions.md +4 -1
- data/karma.conf.js +0 -3
- data/lib/generators/shopify_app/install/templates/shopify_app.rb.tt +2 -2
- data/lib/shopify_app/admin_api/with_token_refetch.rb +1 -2
- data/lib/shopify_app/configuration.rb +6 -4
- data/lib/shopify_app/controller_concerns/csrf_protection.rb +2 -1
- data/lib/shopify_app/controller_concerns/embedded_app.rb +5 -1
- data/lib/shopify_app/controller_concerns/localization.rb +1 -1
- data/lib/shopify_app/controller_concerns/login_protection.rb +8 -1
- data/lib/shopify_app/controller_concerns/token_exchange.rb +12 -8
- data/lib/shopify_app/controller_concerns/with_shopify_id_token.rb +16 -9
- data/lib/shopify_app/engine.rb +4 -9
- data/lib/shopify_app/utils.rb +10 -1
- data/lib/shopify_app/version.rb +1 -1
- data/package.json +1 -1
- data/shopify_app.gemspec +2 -1
- data/yarn.lock +8 -8
- metadata +23 -26
- data/app/assets/images/storage_access.svg +0 -1
- data/app/assets/javascripts/shopify_app/app_bridge_3.7.8.js +0 -10
- data/app/assets/javascripts/shopify_app/app_bridge_redirect.js +0 -22
data/config/locales/pl.yml
CHANGED
@@ -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
|
data/config/locales/pt-BR.yml
CHANGED
@@ -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
|
data/config/locales/pt-PT.yml
CHANGED
@@ -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
|
data/config/locales/sv.yml
CHANGED
@@ -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
|
data/config/locales/th.yml
CHANGED
@@ -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: ดำเนินการต่อ
|
data/config/locales/tr.yml
CHANGED
@@ -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
|
data/config/locales/vi.yml
CHANGED
@@ -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
|
data/config/locales/zh-CN.yml
CHANGED
@@ -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: 继续
|
data/config/locales/zh-TW.yml
CHANGED
@@ -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](
|
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.
|
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
|
@@ -11,8 +11,7 @@ module ShopifyApp
|
|
11
11
|
ShopifyApp::Logger.debug("Encountered error: #{error.code} - #{error.response.inspect}, re-raising")
|
12
12
|
elsif retrying
|
13
13
|
ShopifyApp::Logger.debug("Shopify API returned a 401 Unauthorized error that was not corrected " \
|
14
|
-
"with token exchange,
|
15
|
-
ShopifyApp::SessionRepository.delete_session(session.id)
|
14
|
+
"with token exchange, re-raising error")
|
16
15
|
else
|
17
16
|
retrying = true
|
18
17
|
ShopifyApp::Logger.debug("Shopify API returned a 401 Unauthorized error, exchanging token and " \
|
@@ -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
|
-
|
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
|
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
|
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
|
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
|
-
|
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
|
-
|
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] =
|
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
|
-
|
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
|
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
|
94
|
-
|
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
|
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
|
-
|
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
|
-
|
28
|
+
jwt_payload&.shopify_user_id
|
17
29
|
end
|
18
30
|
|
19
31
|
def jwt_expire_at
|
20
|
-
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
|
data/lib/shopify_app/engine.rb
CHANGED
@@ -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?)
|
data/lib/shopify_app/utils.rb
CHANGED
@@ -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
|
data/lib/shopify_app/version.rb
CHANGED
data/package.json
CHANGED
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.
|
1553
|
-
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.
|
1554
|
-
integrity sha512-
|
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.
|
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.
|
1988
|
-
version "7.
|
1989
|
-
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.
|
1990
|
-
integrity sha512-
|
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
|
|