shopify_app 17.0.5 → 18.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -0
- data/.github/ISSUE_TEMPLATE/bug-report.md +63 -0
- data/.github/ISSUE_TEMPLATE/config.yml +1 -0
- data/.github/ISSUE_TEMPLATE/feature-request.md +33 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -1
- data/.github/workflows/build.yml +4 -1
- data/CHANGELOG.md +26 -0
- data/CONTRIBUTING.md +76 -0
- data/Gemfile.lock +103 -91
- data/README.md +72 -593
- data/app/controllers/concerns/shopify_app/shop_access_scopes_verification.rb +32 -0
- data/app/controllers/shopify_app/callback_controller.rb +17 -2
- data/app/controllers/shopify_app/sessions_controller.rb +5 -1
- data/app/views/shopify_app/shared/post_redirect_to_auth_shopify.html.erb +21 -0
- data/config/locales/nl.yml +1 -1
- data/docs/Quickstart.md +15 -77
- data/docs/Troubleshooting.md +142 -4
- data/docs/Upgrading.md +126 -0
- data/docs/shopify_app/authentication.md +124 -0
- data/docs/shopify_app/engine.md +82 -0
- data/docs/shopify_app/generators.md +127 -0
- data/docs/shopify_app/handling-access-scopes-changes.md +14 -0
- data/docs/shopify_app/script-tags.md +28 -0
- data/docs/shopify_app/session-repository.md +88 -0
- data/docs/shopify_app/testing.md +38 -0
- data/docs/shopify_app/webhooks.md +72 -0
- data/lib/generators/shopify_app/home_controller/templates/home_controller.rb +10 -0
- data/lib/generators/shopify_app/home_controller/templates/index.html.erb +1 -1
- data/lib/generators/shopify_app/home_controller/templates/unauthenticated_home_controller.rb +2 -0
- data/lib/generators/shopify_app/install/install_generator.rb +30 -1
- data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +2 -1
- data/lib/generators/shopify_app/install/templates/omniauth.rb +1 -0
- data/lib/generators/shopify_app/install/templates/shopify_app.js +1 -1
- data/lib/generators/shopify_app/install/templates/shopify_app.rb.tt +5 -2
- data/lib/generators/shopify_app/install/templates/shopify_provider.rb.tt +8 -0
- data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +27 -0
- data/lib/generators/shopify_app/shop_model/templates/db/migrate/add_shop_access_scopes_column.erb +5 -0
- data/lib/generators/shopify_app/shop_model/templates/shop.rb +1 -1
- data/lib/generators/shopify_app/shopify_app_generator.rb +1 -1
- data/lib/generators/shopify_app/user_model/templates/db/migrate/add_user_access_scopes_column.erb +5 -0
- data/lib/generators/shopify_app/user_model/templates/user.rb +1 -1
- data/lib/generators/shopify_app/user_model/user_model_generator.rb +27 -0
- data/lib/shopify_app.rb +11 -0
- data/lib/shopify_app/access_scopes/noop_strategy.rb +13 -0
- data/lib/shopify_app/access_scopes/shop_strategy.rb +24 -0
- data/lib/shopify_app/access_scopes/user_strategy.rb +41 -0
- data/lib/shopify_app/configuration.rb +22 -0
- data/lib/shopify_app/controller_concerns/login_protection.rb +10 -3
- data/lib/shopify_app/middleware/same_site_cookie_middleware.rb +1 -1
- data/lib/shopify_app/omniauth/omniauth_configuration.rb +64 -0
- data/lib/shopify_app/session/in_memory_shop_session_store.rb +9 -7
- data/lib/shopify_app/session/in_memory_user_session_store.rb +9 -7
- data/lib/shopify_app/session/shop_session_storage_with_scopes.rb +58 -0
- data/lib/shopify_app/session/user_session_storage_with_scopes.rb +58 -0
- data/lib/shopify_app/utils.rb +12 -0
- data/lib/shopify_app/version.rb +1 -1
- data/package.json +1 -1
- data/service.yml +1 -4
- data/shopify_app.gemspec +5 -4
- data/yarn.lock +22 -22
- metadata +50 -16
- data/.github/ISSUE_TEMPLATE.md +0 -19
- data/docs/install-on-dev-shop.png +0 -0
- data/docs/test-your-app.png +0 -0
- data/lib/generators/shopify_app/install/templates/shopify_provider.rb +0 -20
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShopifyApp
|
4
|
+
module ShopAccessScopesVerification
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_action :login_on_scope_changes
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def login_on_scope_changes
|
14
|
+
redirect_to(shop_login) if scopes_mismatch?
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def scopes_mismatch?
|
20
|
+
ShopifyApp.configuration.shop_access_scopes_strategy.update_access_scopes?(current_shopify_domain)
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_shopify_domain
|
24
|
+
return if params[:shop].blank?
|
25
|
+
ShopifyApp::Utils.sanitize_shop_domain(params[:shop])
|
26
|
+
end
|
27
|
+
|
28
|
+
def shop_login
|
29
|
+
ShopifyApp::Utils.shop_login_url(shop: params[:shop], return_to: request.fullpath)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -76,10 +76,20 @@ module ShopifyApp
|
|
76
76
|
if jwt_request?
|
77
77
|
false
|
78
78
|
else
|
79
|
-
ShopifyApp::SessionRepository.user_storage.present?
|
79
|
+
return false unless ShopifyApp::SessionRepository.user_storage.present?
|
80
|
+
update_user_access_scopes?
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
84
|
+
def update_user_access_scopes?
|
85
|
+
return true if user_session.blank?
|
86
|
+
user_access_scopes_strategy.update_access_scopes?(user_id: session[:user_id])
|
87
|
+
end
|
88
|
+
|
89
|
+
def user_access_scopes_strategy
|
90
|
+
ShopifyApp.configuration.user_access_scopes_strategy
|
91
|
+
end
|
92
|
+
|
83
93
|
def jwt_request?
|
84
94
|
jwt_shopify_domain || jwt_shopify_user_id
|
85
95
|
end
|
@@ -118,6 +128,10 @@ module ShopifyApp
|
|
118
128
|
auth_hash['credentials']['token']
|
119
129
|
end
|
120
130
|
|
131
|
+
def access_scopes
|
132
|
+
auth_hash.dig('extra', 'scope')
|
133
|
+
end
|
134
|
+
|
121
135
|
def reset_session_options
|
122
136
|
request.session_options[:renew] = true
|
123
137
|
session.delete(:_csrf_token)
|
@@ -127,7 +141,8 @@ module ShopifyApp
|
|
127
141
|
session_store = ShopifyAPI::Session.new(
|
128
142
|
domain: shop_name,
|
129
143
|
token: token,
|
130
|
-
api_version: ShopifyApp.configuration.api_version
|
144
|
+
api_version: ShopifyApp.configuration.api_version,
|
145
|
+
access_scopes: access_scopes
|
131
146
|
)
|
132
147
|
|
133
148
|
session[:shopify_user] = associated_user
|
@@ -150,7 +150,11 @@ module ShopifyApp
|
|
150
150
|
end
|
151
151
|
|
152
152
|
def authenticate_in_context
|
153
|
-
|
153
|
+
post_redirect_to_auth_shopify
|
154
|
+
end
|
155
|
+
|
156
|
+
def post_redirect_to_auth_shopify
|
157
|
+
render('shopify_app/shared/post_redirect_to_auth_shopify', layout: false)
|
154
158
|
end
|
155
159
|
|
156
160
|
def authenticate_at_top_level
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
6
|
+
<base target="_top">
|
7
|
+
<title>Redirecting…</title>
|
8
|
+
<script>
|
9
|
+
function redirect() {
|
10
|
+
var form = document.getElementById("redirect-form");
|
11
|
+
if (form) {
|
12
|
+
form.submit();
|
13
|
+
}
|
14
|
+
}
|
15
|
+
document.addEventListener("DOMContentLoaded", redirect);
|
16
|
+
</script>
|
17
|
+
</head>
|
18
|
+
<body>
|
19
|
+
<%= form_tag '/auth/shopify', id: 'redirect-form' %>
|
20
|
+
</body>
|
21
|
+
</html>
|
data/config/locales/nl.yml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
nl:
|
3
3
|
logged_out: Je bent afgemeld
|
4
|
-
could_not_log_in: Kon niet
|
4
|
+
could_not_log_in: Kon niet inloggen bij Shopify-winkel
|
5
5
|
invalid_shop_url: Ongeldig winkeldomein
|
6
6
|
enable_cookies_heading: Schakel cookies in van %{app}
|
7
7
|
enable_cookies_body: Je moet cookies in deze browser handmatig inschakelen om %{app}
|
data/docs/Quickstart.md
CHANGED
@@ -1,93 +1,31 @@
|
|
1
|
-
Quickstart
|
2
|
-
==========
|
1
|
+
# Quickstart
|
3
2
|
|
4
|
-
|
5
|
-
This guide assumes you have Ruby, Rails and PostgreSQL installed on your computer already; if you haven't done that already start with [this guide.](https://guides.rubyonrails.org/v5.0/getting_started.html#installing-rails)
|
3
|
+
This guide assumes you have completed the steps to create a new Rails app using the Shopify App gem found in the [*Usage*](/README.md#usage) section of the project's [*README*](/README.md).
|
6
4
|
|
7
|
-
|
8
|
-
--------------------------------
|
5
|
+
#### Table of contents
|
9
6
|
|
10
|
-
|
7
|
+
[Make your app available to the internet](#make-your-app-available-to-the-internet)
|
11
8
|
|
12
|
-
|
13
|
-
$ rails new test-app --database=postgresql
|
14
|
-
$ cd test-app
|
15
|
-
$ git init
|
16
|
-
$ git add .
|
17
|
-
$ git commit -m 'new rails app'
|
18
|
-
```
|
19
|
-
|
20
|
-
2. Create a new Heroku app
|
21
|
-
--------------------------
|
22
|
-
|
23
|
-
The next step is to create a new Heroku app to host your application. If you haven't got a Heroku account yet, create a free account [here](https://www.heroku.com/).
|
24
|
-
|
25
|
-
Head to the Heroku dashboard and create a new app, or run the following commands with the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli#download-and-install) installed, substituting `name` for the name of your own app:
|
26
|
-
|
27
|
-
CLI:
|
28
|
-
```sh
|
29
|
-
$ heroku create name
|
30
|
-
```
|
31
|
-
|
32
|
-
3. Create a new App in the Shopify Partner dashboard
|
33
|
-
-----------------------------------------
|
34
|
-
* Create a Shopify app in the [Partners dashboard](https://partner.shopify.com). For this tutorial, you can choose either a public or custom app, but you can [learn about App Types here.](https://help.shopify.com/en/manual/apps/app-types)
|
35
|
-
[https://app.shopify.com/services/partners/api_clients](https://app.shopify.com/services/partners/api_clients)
|
36
|
-
* Set the callback url to `https://<appname>.herokuapp.com/`
|
37
|
-
* Choose an embedded app
|
38
|
-
* Set the app's `redirect_uri` to `https://<appname>.herokuapp.com/auth/shopify/callback`
|
39
|
-
|
40
|
-
4. Add ShopifyApp to Gemfile
|
41
|
-
----------------------------
|
42
|
-
|
43
|
-
Run this command to add the `shopify_app` Gem to your app:
|
9
|
+
[Use Shopify App Bridge to embed your app in the Shopify Admin](#use-shopify-app-bridge-to-embed-your-app-in-the-shopify-admin)
|
44
10
|
|
45
|
-
|
46
|
-
$ bundle add shopify_app
|
47
|
-
```
|
11
|
+
## Make your app available to the internet
|
48
12
|
|
49
|
-
|
13
|
+
Your local app needs to be accessible from the public Internet in order to install it on a Shopify store, to use the [App Proxy Controller](/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_controller.rb) or receive [webhooks](/docs/shopify_app/webhooks.md).
|
50
14
|
|
51
|
-
|
52
|
-
-------------------------------
|
15
|
+
Use a tunneling service like [ngrok](https://ngrok.com/), [Beeceptor](https://beeceptor.com/), [Mockbin](http://mockbin.org/), or [Hookbin](https://hookbin.com/) to make your development environment accessible to the internet.
|
53
16
|
|
54
|
-
|
17
|
+
For example with [ngrok](https://ngrok.com/), run this command to set up a tunnel proxy to Rails' default port:
|
55
18
|
|
56
19
|
```sh
|
57
|
-
|
58
|
-
$ rails generate shopify_app
|
59
|
-
$ git add .
|
60
|
-
$ git commit -m 'generated shopify app'
|
20
|
+
ngrok http 3000
|
61
21
|
```
|
62
22
|
|
63
|
-
|
64
|
-
README for further details on how to set this up.
|
65
|
-
|
66
|
-
6. Deploy your app
|
67
|
-
---------
|
68
|
-
|
69
|
-
Once you've generated your app, push it into your Heroku environment to see it up and running:
|
70
|
-
```sh
|
71
|
-
$ git push heroku
|
72
|
-
$ heroku run rake db:migrate
|
73
|
-
```
|
74
|
-
|
75
|
-
7. Install the App!
|
76
|
-
-------------------
|
77
|
-
|
78
|
-
Ensure you have created a [development store](https://help.shopify.com/en/api/getting-started/making-your-first-request#create-a-development-store) using the Shopify Partner Dashboard. If you don't already have one, [create one by following these instructions](https://help.shopify.com/en/api/getting-started/making-your-first-request#create-a-development-store).
|
79
|
-
|
80
|
-
##### Note: The following step will cause your store to become `transfer-disabled.` Read more about store transfer and why it's important [here](https://help.shopify.com/en/api/guides/store-transfers#transfer-disabled-stores). This is an irreversible change, so be sure you don't plan to transfer this store to a merchant.
|
81
|
-
|
82
|
-
Install the app onto your new development store using the Partner Dashboard. Log in to your account, visit the apps page, click the app you created earlier, and looking for the `Test your app` instructions where you can select a store to install your app on.
|
83
|
-
|
84
|
-
![Installing an app on the partners dashboard dropdown](/docs/install-on-dev-shop.png)
|
23
|
+
See the [*Embed the app in Shopify*](https://shopify.dev/tutorials/build-rails-react-app-that-uses-app-bridge-authentication#embed-the-app-in-shopify) section of [*Build a Shopify app with Rails, React, and App Bridge*](https://shopify.dev/tutorials/build-rails-react-app-that-uses-app-bridge-authentication) to learn more.
|
85
24
|
|
86
|
-
|
25
|
+
## Use Shopify App Bridge to embed your app in the Shopify Admin
|
87
26
|
|
88
|
-
|
27
|
+
A basic example of using [*Shopify App Bridge*](https://shopify.dev/tools/app-bridge) is included in the install generator. An instance Shopify App Bridge is automatically initialized in [shopify_app.js](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/shopify_app.js).
|
89
28
|
|
90
|
-
|
91
|
-
-------------------
|
29
|
+
The [flash_messages.js](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/flash_messages.js) file converts Rails [flash messages](https://api.rubyonrails.org/classes/ActionDispatch/Flash.html) to App Bridge Toast actions automatically. By default, this library is included via [unpkg in the embedded_app layout](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/embedded_app.html.erb#L27).
|
92
30
|
|
93
|
-
|
31
|
+
For more advanced uses it is recommended to [install App Bridge via npm or yarn](https://help.shopify.com/en/api/embedded-apps/app-bridge/getting-started#set-up-shopify-app-bridge-in-your-app).
|
data/docs/Troubleshooting.md
CHANGED
@@ -1,7 +1,26 @@
|
|
1
|
-
Troubleshooting Shopify App
|
2
|
-
===========
|
1
|
+
# Troubleshooting Shopify App
|
3
2
|
|
4
|
-
|
3
|
+
#### Table of contents
|
4
|
+
|
5
|
+
[Generators](#generators)
|
6
|
+
* [The `shopify_app:install` generator hangs](#the-shopifyappinstall-generator-hangs)
|
7
|
+
|
8
|
+
[Rails](#rails)
|
9
|
+
* [Known issues with Rails `v6.1`](#known-issues-with-rails-v61)
|
10
|
+
|
11
|
+
[App installation](#app-installation)
|
12
|
+
* [My app won't install](#my-app-wont-install)
|
13
|
+
* [My app keeps redirecting to login](#my-app-keeps-redirecting-to-login)
|
14
|
+
|
15
|
+
[JWT session tokens](#jwt-session-tokens)
|
16
|
+
* [My app is still using cookies to authenticate](#my-app-is-still-using-cookies-to-authenticate)
|
17
|
+
* [My app can't make requests to the Shopify API](#my-app-cant-make-requests-to-the-shopify-api)
|
18
|
+
|
19
|
+
[Migrating to App Bridge 2.0](#migrating-to-app-bridge-2.0)
|
20
|
+
|
21
|
+
## Generators
|
22
|
+
|
23
|
+
### The shopify_app:install generator hangs
|
5
24
|
|
6
25
|
Rails uses spring by default to speed up development. To run the generator, spring has to be stopped:
|
7
26
|
|
@@ -11,6 +30,125 @@ $ bundle exec spring stop
|
|
11
30
|
|
12
31
|
Run shopify_app generator again.
|
13
32
|
|
14
|
-
|
33
|
+
## Rails
|
34
|
+
|
35
|
+
### Known issues with Rails `v6.1`
|
36
|
+
|
37
|
+
If you recently upgraded your application's `Rails::Application` configuration to load the default configuration for Rails `v6.1`, then you will need to update the following `cookies_same_site_protection` ActionDispatch configuration.
|
38
|
+
|
39
|
+
```diff
|
40
|
+
# config/application.rb
|
41
|
+
|
42
|
+
require_relative 'boot'
|
43
|
+
|
44
|
+
require 'rails/all'
|
45
|
+
|
46
|
+
Bundler.require(*Rails.groups)
|
47
|
+
|
48
|
+
module AppName
|
49
|
+
class Application < Rails::Application
|
50
|
+
+ config.load_defaults 6.1
|
51
|
+
|
52
|
+
+ config.action_dispatch.cookies_same_site_protection = :none
|
53
|
+
...
|
54
|
+
end
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
As of Rails `v6.1`, the same-site cookie protection setting defaults to `Lax`. This does not allow an embedded app to make cross-domain requests in the Shopify Admin.
|
59
|
+
|
60
|
+
Alternatively, you can upgrade to [`v17.2.0` of the shopify_app gem](/docs/Upgrading.md#upgrading-to-v1720).
|
61
|
+
|
62
|
+
## App installation
|
63
|
+
|
64
|
+
### My app won't install
|
65
|
+
|
66
|
+
#### App installation fails with 'The page you’re looking for could not be found' if the app was installed before
|
15
67
|
|
16
68
|
This issue can occur when the session (the model you set as `ShopifyApp::SessionRepository.storage`) isn't deleted when the user uninstalls your app. A possible fix for this is listening to the `app/uninstalled` webhook and deleting the corresponding session in the webhook handler.
|
69
|
+
|
70
|
+
## JWT session tokens
|
71
|
+
|
72
|
+
### My app is still using cookies to authenticate
|
73
|
+
|
74
|
+
#### `shopify_app` gem version
|
75
|
+
|
76
|
+
Ensure the app is using shopify_app gem v13.x.x+. See [*Upgrading to `v13.0.0`*](/docs/Upgrading.md#upgrading-to-v1300).
|
77
|
+
|
78
|
+
#### `shopify_app` gem Rails configuration
|
79
|
+
|
80
|
+
Edit `config/initializer/shopify_app.rb` and ensure the following configurations are set:
|
81
|
+
|
82
|
+
```diff
|
83
|
+
+ config.embedded_app = true
|
84
|
+
|
85
|
+
+ config.allow_jwt_authentication = true
|
86
|
+
+ config.allow_cookie_authentication = false
|
87
|
+
|
88
|
+
# This line should already exist if you're using shopify_app gem 13.x.x+
|
89
|
+
+ config.shop_session_repository = 'Shop'
|
90
|
+
```
|
91
|
+
|
92
|
+
#### Inspect server logs
|
93
|
+
|
94
|
+
If you have checked the configurations above, and the app is still using cookies, then it is possible that the `shopify_app` gem defaulted to relying on cookies. This would happen when your browser allows third-party cookies and a session token was not successfully found as part of your request.
|
95
|
+
|
96
|
+
In this case, check the server logs to see if the session token was invalid:
|
97
|
+
|
98
|
+
```los
|
99
|
+
[ShopifyApp::JWT] Failed to validate JWT: [JWT::<Error>] <Failure message>
|
100
|
+
```
|
101
|
+
|
102
|
+
*Example*
|
103
|
+
|
104
|
+
```
|
105
|
+
[ShopifyApp::JWT] Failed to validate JWT: [JWT::ImmatureSignature] Signature nbf has not been reached
|
106
|
+
```
|
107
|
+
|
108
|
+
**Note:** In a local development environment, you may want to temporarily update your `Gemfile` to point to a local instance of the `shopify_app` library instad of an installed gem. This will enable you to use a debugging tool like `byebug` to debug the library.
|
109
|
+
|
110
|
+
```diff
|
111
|
+
- gem 'shopify_app', '~> 14.2'
|
112
|
+
+ gem 'shopify_app', path: '/path/to/shopify_app'
|
113
|
+
```
|
114
|
+
|
115
|
+
### My app can't make requests to the Shopify API
|
116
|
+
|
117
|
+
> **Note:** Session tokens cannot be used to make authenticated requests to the Shopify API. Learn more about authenticating your backend requests to Shopify APIs at [Shopify API authentication](https://shopify.dev/concepts/about-apis/authentication).
|
118
|
+
|
119
|
+
#### The Shopify API returns `401 Unauthorized`
|
120
|
+
|
121
|
+
If your app uses [user-based token storage](/docs/shopify_app/session-repository.md#user-based-token-storage), then your app is configured to use **online** access tokens (see [API access modes](https://shopify.dev/concepts/about-apis/authentication#api-access-modes) to learn the difference between "online" and "offline" access tokens ). Unlike offline access tokens, online access tokens expire daily and cannot be used to make authenticated requests to the Shopify API once they expire.
|
122
|
+
|
123
|
+
Converting your app to use session tokens means that your app will most likely not go through the OAuth flow as often as it did when relying on cookie sessions. Since the online access tokens stored in your app's database are refreshed during OAuth, this may cause your app's user session repository to use expired online access tokens.
|
124
|
+
|
125
|
+
If the Shopify API returns `401 Unauthorized`, handle this error on your app by redirecting the user to your login path to start the OAuth flow. As a result, your app will be given a new online access token for the current user.
|
126
|
+
|
127
|
+
> **Note:** The following are examples to common app configurations. Your specific use-case may differ.
|
128
|
+
|
129
|
+
##### Example solution
|
130
|
+
|
131
|
+
Add the following line to your app's unauthorized response handler:
|
132
|
+
|
133
|
+
```diff
|
134
|
+
+ redirect_to(ShopifyApp.configuration.login_url, shop: current_shopify_domain)
|
135
|
+
```
|
136
|
+
|
137
|
+
_Example:_ If your embedded app cannot handle server-side XHR redirects, then configure your app's unauthorized response handler to set a response header:
|
138
|
+
|
139
|
+
```
|
140
|
+
X-Shopify-API-Request-Failure-Unauthorized: true
|
141
|
+
```
|
142
|
+
|
143
|
+
Then, use the [Shopify App Bridge Redirect](https://shopify.dev/tools/app-bridge/actions/navigation/redirect) action to redirect your app frontend to the app login URL if this header is set.
|
144
|
+
|
145
|
+
## Migrating to App Bridge 2.0
|
146
|
+
|
147
|
+
In order to upgrade your embedded app to the latest App Bridge 2.0 version, please refer to the [migration guide](https://shopify.dev/tutorials/migrate-your-app-to-app-bridge-2).
|
148
|
+
|
149
|
+
To ensure that your app's embedded layout doesn't import App Bridge 2.0 before fully migrating, make the following change to bind it to v1.x.
|
150
|
+
|
151
|
+
```diff
|
152
|
+
- <script src="https://unpkg.com/@shopify/app-bridge"></script>
|
153
|
+
+ <script src="https://unpkg.com/@shopify/app-bridge@1"></script>
|
154
|
+
```
|
data/docs/Upgrading.md
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
# Upgrading
|
2
|
+
|
3
|
+
This file documents important changes needed to upgrade your app's Shopify App version to a new major version.
|
4
|
+
|
5
|
+
#### Table of contents
|
6
|
+
|
7
|
+
[Upgrading to `v17.2.0`](#upgrading-to-v1720)
|
8
|
+
|
9
|
+
[Upgrading to `v13.0.0`](#upgrading-to-v1300)
|
10
|
+
|
11
|
+
[Upgrading to `v11.7.0`](#upgrading-to-v1170)
|
12
|
+
|
13
|
+
[Upgrading from `v8.6` to `v9.0.0`](#upgrading-from-v86-to-v900)
|
14
|
+
|
15
|
+
## Upgrading to `v17.2.0`
|
16
|
+
|
17
|
+
### Different SameSite cookie attribute behaviour
|
18
|
+
|
19
|
+
To support Rails `v6.1`, the [`SameSiteCookieMiddleware`](/lib/shopify_app/middleware/same_site_cookie_middleware.rb) was updated to configure cookies to `SameSite=None` if the app is embedded. Before this release, cookies were configured to `SameSite=None` only if this attribute had not previously been set before.
|
20
|
+
|
21
|
+
```diff
|
22
|
+
# same_site_cookie_middleware.rb
|
23
|
+
- cookie << '; SameSite=None' unless cookie =~ /;\s*samesite=/i
|
24
|
+
+ cookie << '; SameSite=None' if ShopifyApp.configuration.embedded_app?
|
25
|
+
```
|
26
|
+
|
27
|
+
By default, Rails `v6.1` configures `SameSite=Lax` on all cookies that don't specify this attribute.
|
28
|
+
|
29
|
+
## Upgrading to `v13.0.0`
|
30
|
+
|
31
|
+
Version 13.0.0 adds the ability to use both user and shop sessions, concurrently. This however involved a large
|
32
|
+
change to how session stores work. Here are the steps to migrate to 13.x
|
33
|
+
|
34
|
+
### Changes to `config/initializers/shopify_app.rb`
|
35
|
+
|
36
|
+
- *REMOVE* `config.per_user_tokens = [true|false]` this is no longer needed
|
37
|
+
- *CHANGE* `config.session_repository = 'Shop'` To `config.shop_session_repository = 'Shop'`
|
38
|
+
- *ADD (optional)* User Session Storage `config.user_session_repository = 'User'`
|
39
|
+
|
40
|
+
### Shop Model Changes (normally `app/models/shop.rb`)
|
41
|
+
|
42
|
+
- *CHANGE* `include ShopifyApp::SessionStorage` to `include ShopifyApp::ShopSessionStorage`
|
43
|
+
|
44
|
+
### Changes to the @shop_session instance variable (normally in `app/controllers/*.rb`)
|
45
|
+
|
46
|
+
- *CHANGE* if you are using shop sessions, `@shop_session` will need to be changed to `@current_shopify_session`.
|
47
|
+
|
48
|
+
### Changes to Rails `session`
|
49
|
+
|
50
|
+
- *CHANGE* `session[:shopify]` is no longer set. Use `session[:user_id]` if your app uses user based tokens, or `session[:shop_id]` if your app uses shop based tokens.
|
51
|
+
|
52
|
+
### Changes to `ShopifyApp::LoginProtection`
|
53
|
+
|
54
|
+
`ShopifyApp::LoginProtection`
|
55
|
+
|
56
|
+
- CHANGE if you are using `ShopifyApp::LoginProtection#shopify_session` in your code, it will need to be
|
57
|
+
changed to `ShopifyApp::LoginProtection#activate_shopify_session`
|
58
|
+
- CHANGE if you are using `ShopifyApp::LoginProtection#clear_shop_session` in your code, it will need to be
|
59
|
+
changed to `ShopifyApp::LoginProtection#clear_shopify_session`
|
60
|
+
|
61
|
+
### Notes
|
62
|
+
You do not need a user model; a shop session is fine for most applications.
|
63
|
+
|
64
|
+
---
|
65
|
+
|
66
|
+
## Upgrading to `v11.7.0`
|
67
|
+
|
68
|
+
### Session storage method signature breaking change
|
69
|
+
If you override `def self.store(auth_session)` method in your session storage model (e.g. Shop), the method signature has changed to `def self.store(auth_session, *args)` in order to support user-based token storage. Please update your method signature to include the second argument.
|
70
|
+
|
71
|
+
---
|
72
|
+
|
73
|
+
## Upgrading from `v8.6` to `v9.0.0`
|
74
|
+
|
75
|
+
### Configuration change
|
76
|
+
|
77
|
+
Add an API version configuration in `config/initializers/shopify_app.rb`
|
78
|
+
Set this to the version you want to run against by default. See [Shopify API docs](https://help.shopify.com/en/api/versioning) for versions available.
|
79
|
+
```ruby
|
80
|
+
config.api_version = '2019-04'
|
81
|
+
```
|
82
|
+
|
83
|
+
### Session storage change
|
84
|
+
|
85
|
+
You will need to add an `api_version` method to your session storage object. The default implementation for this is.
|
86
|
+
```ruby
|
87
|
+
def api_version
|
88
|
+
ShopifyApp.configuration.api_version
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
### Generated file change
|
93
|
+
|
94
|
+
`embedded_app.html.erb` the usage of `shop_session.url` needs to be changed to `shop_session.domain`
|
95
|
+
```erb
|
96
|
+
<script type="text/javascript">
|
97
|
+
ShopifyApp.init({
|
98
|
+
apiKey: "<%= ShopifyApp.configuration.api_key %>",
|
99
|
+
|
100
|
+
shopOrigin: "<%= "https://#{ @shop_session.url }" if @shop_session %>",
|
101
|
+
|
102
|
+
debug: false,
|
103
|
+
forceRedirect: true
|
104
|
+
});
|
105
|
+
</script>
|
106
|
+
```
|
107
|
+
is changed to
|
108
|
+
```erb
|
109
|
+
<script type="text/javascript">
|
110
|
+
ShopifyApp.init({
|
111
|
+
apiKey: "<%= ShopifyApp.configuration.api_key %>",
|
112
|
+
|
113
|
+
shopOrigin: "<%= "https://#{ @shop_session.domain }" if @shop_session %>",
|
114
|
+
|
115
|
+
debug: false,
|
116
|
+
forceRedirect: true
|
117
|
+
});
|
118
|
+
</script>
|
119
|
+
```
|
120
|
+
|
121
|
+
### ShopifyAPI changes
|
122
|
+
|
123
|
+
You will need to also follow the ShopifyAPI [upgrade guide](https://github.com/Shopify/shopify_api/blob/master/README.md#-breaking-change-notice-for-version-700-) to ensure your app is ready to work with API versioning.
|
124
|
+
|
125
|
+
[dashboard]:https://partners.shopify.com
|
126
|
+
[app-bridge]:https://help.shopify.com/en/api/embedded-apps/app-bridge
|