shopify_app 14.3.0 → 14.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +5 -0
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +20 -0
- data/README.md +3 -3
- data/app/assets/javascripts/shopify_app/storage_access.js +2 -1
- data/app/assets/javascripts/shopify_app/top_level_interaction.js +1 -1
- data/app/controllers/shopify_app/callback_controller.rb +49 -18
- data/app/controllers/shopify_app/sessions_controller.rb +15 -1
- data/app/views/shopify_app/sessions/enable_cookies.html.erb +1 -6
- data/app/views/shopify_app/sessions/top_level_interaction.html.erb +1 -7
- data/docs/Releasing.md +1 -1
- data/karma.conf.js +1 -1
- data/lib/generators/shopify_app/controllers/controllers_generator.rb +1 -1
- data/lib/generators/shopify_app/views/views_generator.rb +1 -1
- data/lib/shopify_app/controller_concerns/itp.rb +2 -0
- data/lib/shopify_app/controller_concerns/login_protection.rb +14 -2
- data/lib/shopify_app/engine.rb +21 -0
- data/lib/shopify_app/version.rb +1 -1
- data/package.json +6 -7
- data/yarn.lock +1889 -1976
- metadata +2 -3
- data/package-lock.json +0 -7177
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3962aefcffacf58b7e57836a66b40a7689d5fe64d754fe1b236081cfeefcda2
|
4
|
+
data.tar.gz: 3f7200abedcd9598e08e7fcc816009acd236093c5a3ca011fa1d05684b31a1ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3c2eaf95a630a628de9252be8f1802b35ce57be387a5e5ae3e8047484432b5ed7b1af98b739911c1f6afa74b09c44b5f8589481ad699c6595ef95d5332952de
|
7
|
+
data.tar.gz: 312ef3c7dd4013c17696289e9b8890e359d24753501468155cdb3ae63a7ff5a577d4b5f1a3f0606d438e78be655b0df791ccd45406d88485f5386db1a563d9af
|
data/.github/ISSUE_TEMPLATE.md
CHANGED
@@ -12,3 +12,8 @@ Authentication Issues
|
|
12
12
|
A great deal of the issues surrounding this repo are around authenticating (installing) the generated app with Shopify.
|
13
13
|
|
14
14
|
If you are experiencing issues with your app authenticating/installing the best way to get help fast is to create a repo with the minimal amount of code to demonstrate the issue and a clearly documented set of steps you took to arrive there. This will help us solve your problem quicker since we won't need to spend any time figuring out how to reproduce the bug. Please also include your operating system and browser.
|
15
|
+
|
16
|
+
Security
|
17
|
+
--------
|
18
|
+
|
19
|
+
Please be certain to redact any private information from your logs or code snippets such as Api Keys, Api Secrets, and any authentication tokens such as shop_tokens.
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
14.4.4
|
2
|
+
------
|
3
|
+
* Patch to not log params in ShopifyApp jobs [#1086](https://github.com/Shopify/shopify_app/pull/1086)
|
4
|
+
|
5
|
+
14.4.3
|
6
|
+
------
|
7
|
+
* Fix to ensure post authenticate jobs are run after callback requests [#1079](https://github.com/Shopify/shopify_app/pull/1079)
|
8
|
+
|
9
|
+
14.4.2
|
10
|
+
------
|
11
|
+
* Add debug logs in sessions controller
|
12
|
+
|
13
|
+
14.4.1
|
14
|
+
------
|
15
|
+
* Add debug logs for investigating authentication issues
|
16
|
+
|
17
|
+
14.4.0
|
18
|
+
------
|
19
|
+
* Replace script tags for ITP screens with data attributes
|
20
|
+
|
1
21
|
14.3.0
|
2
22
|
------
|
3
23
|
* Create user session if one does not exist but was expected
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ Table of Contents
|
|
26
26
|
- [Troubleshooting](#troubleshooting)
|
27
27
|
- [Testing an embedded app outside the Shopify admin](#testing-an-embedded-app-outside-the-shopify-admin)
|
28
28
|
- [Migration to 13.0.0](#migrating-to-1300)
|
29
|
-
- [Questions or problems?](#questions-or-problems
|
29
|
+
- [Questions or problems?](#questions-or-problems)
|
30
30
|
- [Rails 6 Compatibility](#rails-6-compatibility)
|
31
31
|
- [Upgrading from 8.6 to 9.0.0](#upgrading-from-86-to-900)
|
32
32
|
|
@@ -105,7 +105,7 @@ Options include:
|
|
105
105
|
* `application_name` - the name of your app, it can be supplied with or without double-quotes if a whitespace is present. (e.g. `--application_name Example App` or `--application_name "Example App"`)
|
106
106
|
* `scope` - the OAuth access scope required for your app, e.g. **read_products, write_orders**. *Multiple options* need to be delimited by a comma-space and can be supplied with or without double-quotes
|
107
107
|
(e.g. `--scope read_products, write_orders, write_products` or `--scope "read_products, write_orders, write_products"`)
|
108
|
-
For more information, refer the [docs](http://docs.shopify.com/api/tutorials/oauth).
|
108
|
+
For more information, refer to the [docs](http://docs.shopify.com/api/tutorials/oauth).
|
109
109
|
* `embedded` - the default is to generate an [embedded app](http://docs.shopify.com/embedded-app-sdk), if you want a legacy non-embedded app then set this to false, `--embedded false`
|
110
110
|
|
111
111
|
You can update any of these settings later on easily; the arguments are simply for convenience.
|
@@ -427,7 +427,7 @@ bin/rails g shopify_app:rotate_shopify_token_job
|
|
427
427
|
|
428
428
|
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.
|
429
429
|
|
430
|
-
⚠️ 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/
|
430
|
+
⚠️ 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/initializers/omniauth.rb`:
|
431
431
|
|
432
432
|
```ruby
|
433
433
|
strategy.options[:old_client_secret] = ShopifyApp.configuration.old_secret
|
@@ -132,7 +132,8 @@
|
|
132
132
|
|
133
133
|
/* ITP 2.0 solution: handles cookie partitioning */
|
134
134
|
StorageAccessHelper.prototype.setUpHelper = function() {
|
135
|
-
|
135
|
+
var shopifyData = document.body.dataset;
|
136
|
+
return new ITPHelper({redirectUrl: shopifyData.shopOrigin + "/admin/apps/" + shopifyData.apiKey + shopifyData.returnTo});
|
136
137
|
}
|
137
138
|
|
138
139
|
StorageAccessHelper.prototype.setCookieAndRedirect = function() {
|
@@ -6,46 +6,77 @@ module ShopifyApp
|
|
6
6
|
include ShopifyApp::LoginProtection
|
7
7
|
|
8
8
|
def callback
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
return respond_with_error if invalid_request?
|
10
|
+
|
11
|
+
store_access_token_and_build_session
|
12
12
|
|
13
|
-
if
|
14
|
-
return
|
13
|
+
if start_user_token_flow?
|
14
|
+
return respond_with_user_token_flow
|
15
15
|
end
|
16
16
|
|
17
|
+
perform_post_authenticate_jobs
|
18
|
+
|
19
|
+
respond_successfully
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def respond_successfully
|
17
25
|
if jwt_request?
|
18
|
-
set_shopify_session
|
19
26
|
head(:ok)
|
20
27
|
else
|
28
|
+
redirect_to(return_address)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def respond_with_user_token_flow
|
33
|
+
Rails.logger.debug("[ShopifyApp::CallbackController] Redirecting for user token...")
|
34
|
+
redirect_to(login_url_with_optional_shop)
|
35
|
+
end
|
36
|
+
|
37
|
+
def store_access_token_and_build_session
|
38
|
+
if native_browser_request?
|
39
|
+
Rails.logger.debug("[ShopifyApp::CallbackController] Not a JWT request. Resetting session options...")
|
21
40
|
reset_session_options
|
22
|
-
|
41
|
+
else
|
42
|
+
Rails.logger.debug("[ShopifyApp::CallbackController] JWT request detected. Setting shopify session...")
|
43
|
+
end
|
44
|
+
set_shopify_session
|
45
|
+
end
|
23
46
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
47
|
+
def invalid_request?
|
48
|
+
return true unless auth_hash
|
27
49
|
|
28
|
-
|
29
|
-
|
30
|
-
perform_after_authenticate_job
|
50
|
+
jwt_request? && !valid_jwt_auth?
|
51
|
+
end
|
31
52
|
|
32
|
-
|
33
|
-
|
53
|
+
def native_browser_request?
|
54
|
+
!jwt_request?
|
34
55
|
end
|
35
56
|
|
36
|
-
|
57
|
+
def perform_post_authenticate_jobs
|
58
|
+
install_webhooks
|
59
|
+
install_scripttags
|
60
|
+
perform_after_authenticate_job
|
61
|
+
end
|
37
62
|
|
38
63
|
def respond_with_error
|
39
64
|
if jwt_request?
|
65
|
+
Rails.logger.debug("[ShopifyApp::CallbackController] Invalid JWT auth detected.")
|
40
66
|
head(:unauthorized)
|
41
67
|
else
|
68
|
+
Rails.logger.debug("[ShopifyApp::CallbackController] Invalid non JWT auth detected.")
|
42
69
|
flash[:error] = I18n.t('could_not_log_in')
|
43
70
|
redirect_to(login_url_with_optional_shop)
|
44
71
|
end
|
45
72
|
end
|
46
73
|
|
47
|
-
def
|
48
|
-
|
74
|
+
def start_user_token_flow?
|
75
|
+
if jwt_request?
|
76
|
+
false
|
77
|
+
else
|
78
|
+
ShopifyApp::SessionRepository.user_storage.present? && user_session.blank?
|
79
|
+
end
|
49
80
|
end
|
50
81
|
|
51
82
|
def jwt_request?
|
@@ -10,14 +10,19 @@ module ShopifyApp
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def new
|
13
|
-
|
13
|
+
if sanitized_shop_name.present?
|
14
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Sanitized shop name present. Authenticating...")
|
15
|
+
authenticate
|
16
|
+
end
|
14
17
|
end
|
15
18
|
|
16
19
|
def create
|
20
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Authenticating...")
|
17
21
|
authenticate
|
18
22
|
end
|
19
23
|
|
20
24
|
def enable_cookies
|
25
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Enabling cookies...")
|
21
26
|
return unless validate_shop_presence
|
22
27
|
|
23
28
|
render(:enable_cookies, layout: false, locals: {
|
@@ -40,6 +45,7 @@ module ShopifyApp
|
|
40
45
|
end
|
41
46
|
|
42
47
|
def granted_storage_access
|
48
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Granted storage access.")
|
43
49
|
return unless validate_shop_presence
|
44
50
|
|
45
51
|
session['shopify.granted_storage_access'] = true
|
@@ -50,6 +56,7 @@ module ShopifyApp
|
|
50
56
|
end
|
51
57
|
|
52
58
|
def destroy
|
59
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Resetting session.")
|
53
60
|
reset_session
|
54
61
|
flash[:notice] = I18n.t('.logged_out')
|
55
62
|
redirect_to(login_url_with_optional_shop)
|
@@ -66,18 +73,23 @@ module ShopifyApp
|
|
66
73
|
set_user_tokens_option
|
67
74
|
|
68
75
|
if user_agent_can_partition_cookies
|
76
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Authenticating with partitioning...")
|
69
77
|
authenticate_with_partitioning
|
70
78
|
else
|
79
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Authenticating normally...")
|
71
80
|
authenticate_normally
|
72
81
|
end
|
73
82
|
end
|
74
83
|
|
75
84
|
def authenticate_normally
|
76
85
|
if request_storage_access?
|
86
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Redirecting to request storage access...")
|
77
87
|
redirect_to_request_storage_access
|
78
88
|
elsif authenticate_in_context?
|
89
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Authenticating in context...")
|
79
90
|
authenticate_in_context
|
80
91
|
else
|
92
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Authenticating at top level...")
|
81
93
|
authenticate_at_top_level
|
82
94
|
end
|
83
95
|
end
|
@@ -95,6 +107,7 @@ module ShopifyApp
|
|
95
107
|
# rubocop:disable Lint/SuppressedException
|
96
108
|
def set_user_tokens_option
|
97
109
|
if shop_session.blank?
|
110
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Shop session is blank.")
|
98
111
|
session[:user_tokens] = false
|
99
112
|
return
|
100
113
|
end
|
@@ -117,6 +130,7 @@ module ShopifyApp
|
|
117
130
|
def validate_shop_presence
|
118
131
|
@shop = sanitized_shop_name
|
119
132
|
unless @shop
|
133
|
+
Rails.logger.debug("[ShopifyApp::SessionsController] Invalid shop detected.")
|
120
134
|
render_invalid_shop_error
|
121
135
|
return false
|
122
136
|
end
|
@@ -14,15 +14,10 @@
|
|
14
14
|
display: none;
|
15
15
|
}
|
16
16
|
</style>
|
17
|
-
<script>
|
18
|
-
window.apiKey = "<%= ShopifyApp.configuration.api_key %>";
|
19
|
-
window.shopOrigin = "https://<%= @shop %>";
|
20
|
-
window.returnTo = "<%= params[:return_to] %>"
|
21
|
-
</script>
|
22
17
|
|
23
18
|
<%= javascript_include_tag('shopify_app/enable_cookies', crossorigin: 'anonymous', integrity: true) %>
|
24
19
|
</head>
|
25
|
-
<body>
|
20
|
+
<body data-api-key="<%= ShopifyApp.configuration.api_key %>" data-shop-origin="https://<%= @shop %>" data-redirect-url="<%= @url %>">
|
26
21
|
<%=
|
27
22
|
content_tag(
|
28
23
|
:div, nil,
|
@@ -15,15 +15,9 @@
|
|
15
15
|
}
|
16
16
|
</style>
|
17
17
|
|
18
|
-
<script>
|
19
|
-
window.apiKey = "<%= ShopifyApp.configuration.api_key %>";
|
20
|
-
window.shopOrigin = "https://<%= @shop %>";
|
21
|
-
window.redirectUrl = "<%= @url %>";
|
22
|
-
</script>
|
23
|
-
|
24
18
|
<%= javascript_include_tag('shopify_app/top_level', crossorigin: 'anonymous', integrity: true) %>
|
25
19
|
</head>
|
26
|
-
<body>
|
20
|
+
<body data-api-key="<%= ShopifyApp.configuration.api_key %>" data-shop-origin="https://<%= @shop %>" data-redirect-url="<%= @url %>">
|
27
21
|
<main id="TopLevelInteractionContent">
|
28
22
|
<div class="Polaris-Page">
|
29
23
|
<div class="Polaris-Page__Content">
|
data/docs/Releasing.md
CHANGED
@@ -8,7 +8,7 @@ Releasing ShopifyApp
|
|
8
8
|
- Change the title of the PR to something like: "Packaging for release X.Y.Z"
|
9
9
|
1. Merge your pull request
|
10
10
|
1. Checkout and pull from master so you have the latest version of the shopify_app
|
11
|
-
1. Tag the HEAD with the version
|
11
|
+
1. Tag the HEAD with the version
|
12
12
|
```bash
|
13
13
|
$ git tag -f vX.Y.Z && git push --tags --force
|
14
14
|
```
|
data/karma.conf.js
CHANGED
@@ -8,7 +8,7 @@ module.exports = function(config) {
|
|
8
8
|
config.set({
|
9
9
|
mode: 'development',
|
10
10
|
basePath: '',
|
11
|
-
frameworks: ['mocha
|
11
|
+
frameworks: ['mocha', 'chai-sinon'],
|
12
12
|
files: [
|
13
13
|
'app/assets/javascripts/**/*.js',
|
14
14
|
'test/javascripts/**/*test.js',
|
@@ -13,10 +13,12 @@ module ShopifyApp
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def set_top_level_oauth_cookie
|
16
|
+
Rails.logger.debug("[ShopifyApp::Itp] Setting top level oauth cookie...")
|
16
17
|
session['shopify.top_level_oauth'] = true
|
17
18
|
end
|
18
19
|
|
19
20
|
def clear_top_level_oauth_cookie
|
21
|
+
Rails.logger.debug("[ShopifyApp::Itp] Clearing top level oauth cookie...")
|
20
22
|
session.delete('shopify.top_level_oauth')
|
21
23
|
end
|
22
24
|
|
@@ -18,17 +18,24 @@ module ShopifyApp
|
|
18
18
|
|
19
19
|
def activate_shopify_session
|
20
20
|
if user_session_expected? && user_session.blank?
|
21
|
+
Rails.logger.debug("[ShopifyApp::LoginProtection] User session required. Redirecting to login...")
|
21
22
|
signal_access_token_required
|
22
23
|
return redirect_to_login
|
23
24
|
end
|
24
25
|
|
25
|
-
|
26
|
+
if current_shopify_session.blank?
|
27
|
+
Rails.logger.debug("[ShopifyApp::LoginProtection] Current shopify session is blank. Redirecting to login...")
|
28
|
+
return redirect_to_login
|
29
|
+
end
|
30
|
+
|
26
31
|
clear_top_level_oauth_cookie
|
27
32
|
|
28
33
|
begin
|
34
|
+
Rails.logger.debug("[ShopifyApp::LoginProtection] Activating session...")
|
29
35
|
ShopifyAPI::Base.activate_session(current_shopify_session)
|
30
36
|
yield
|
31
37
|
ensure
|
38
|
+
Rails.logger.debug("[ShopifyApp::LoginProtection] Clearing session...")
|
32
39
|
ShopifyAPI::Base.clear_session
|
33
40
|
end
|
34
41
|
end
|
@@ -71,8 +78,12 @@ module ShopifyApp
|
|
71
78
|
|
72
79
|
def login_again_if_different_user_or_shop
|
73
80
|
if session[:user_session].present? && params[:session].present? # session data was sent/stored correctly
|
81
|
+
Rails.logger.debug("[ShopifyApp::LoginProtection] Session data was sent/stored correctly.")
|
74
82
|
clear_session = session[:user_session] != params[:session] # current user is different from stored user
|
75
|
-
|
83
|
+
if clear_session
|
84
|
+
Rails.logger.debug("[ShopifyApp::LoginProtection] Current user is different from stored user.")
|
85
|
+
end
|
86
|
+
clear_session
|
76
87
|
end
|
77
88
|
|
78
89
|
if current_shopify_session &&
|
@@ -82,6 +93,7 @@ module ShopifyApp
|
|
82
93
|
end
|
83
94
|
|
84
95
|
if clear_session
|
96
|
+
Rails.logger.debug("[ShopifyApp::LoginProtection] Clearing shopify session and redirecting to login...")
|
85
97
|
clear_shopify_session
|
86
98
|
redirect_to_login
|
87
99
|
end
|
data/lib/shopify_app/engine.rb
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module ShopifyApp
|
3
|
+
module RedactJobParams
|
4
|
+
private
|
5
|
+
|
6
|
+
def args_info(job)
|
7
|
+
log_disabled_classes = %w(ShopifyApp::ScripttagsManagerJob ShopifyApp::WebhooksManagerJob)
|
8
|
+
return "" if log_disabled_classes.include?(job.class.name)
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
3
13
|
class Engine < Rails::Engine
|
4
14
|
engine_name 'shopify_app'
|
5
15
|
isolate_namespace ShopifyApp
|
@@ -21,5 +31,16 @@ module ShopifyApp
|
|
21
31
|
app.config.middleware.insert_after(ShopifyApp::SameSiteCookieMiddleware, ShopifyApp::JWTMiddleware)
|
22
32
|
end
|
23
33
|
end
|
34
|
+
|
35
|
+
initializer "shopify_app.redact_job_params" do
|
36
|
+
ActiveSupport.on_load(:active_job) do
|
37
|
+
if ActiveJob::Base.respond_to?(:log_arguments?)
|
38
|
+
WebhooksManagerJob.log_arguments = false
|
39
|
+
ScripttagsManagerJob.log_arguments = false
|
40
|
+
elsif ActiveJob::Logging::LogSubscriber.private_method_defined?(:args_info)
|
41
|
+
ActiveJob::Logging::LogSubscriber.prepend(RedactJobParams)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
24
45
|
end
|
25
46
|
end
|
data/lib/shopify_app/version.rb
CHANGED