shopify_app 22.1.0 → 22.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -48,8 +48,8 @@ module ShopifyApp
48
48
  # takes a ShopifyApp::BillingConfiguration object
49
49
  attr_accessor :billing
50
50
 
51
- # Work in Progress: enables token exchange authentication flow
52
- attr_accessor :wip_new_embedded_auth_strategy
51
+ # Enables new authorization flow using token exchange
52
+ attr_accessor :new_embedded_auth_strategy
53
53
 
54
54
  def initialize
55
55
  @root_url = "/"
@@ -129,7 +129,7 @@ module ShopifyApp
129
129
  end
130
130
 
131
131
  def use_new_embedded_auth_strategy?
132
- wip_new_embedded_auth_strategy && embedded_app?
132
+ new_embedded_auth_strategy && embedded_app?
133
133
  end
134
134
 
135
135
  def online_token_configured?
@@ -5,6 +5,7 @@ module ShopifyApp
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  include ShopifyApp::FrameAncestors
8
+ include ShopifyApp::SanitizedParams
8
9
 
9
10
  included do
10
11
  layout :embedded_app_layout
@@ -13,6 +14,22 @@ module ShopifyApp
13
14
 
14
15
  protected
15
16
 
17
+ def redirect_to_embed_app_in_admin
18
+ ShopifyApp::Logger.debug("Redirecting to embed app in admin")
19
+
20
+ host = if params[:host]
21
+ params[:host]
22
+ elsif params[:shop]
23
+ Base64.encode64("#{sanitized_shop_name}/admin")
24
+ else
25
+ return redirect_to(ShopifyApp.configuration.login_url)
26
+ end
27
+
28
+ redirect_path = ShopifyAPI::Auth.embedded_app_url(host)
29
+ redirect_path = ShopifyApp.configuration.root_url if deduced_phishing_attack?(redirect_path)
30
+ redirect_to(redirect_path, allow_other_host: true)
31
+ end
32
+
16
33
  def use_embedded_app_layout?
17
34
  ShopifyApp.configuration.embedded_app?
18
35
  end
@@ -27,5 +44,15 @@ module ShopifyApp
27
44
  response.set_header("P3P", 'CP="Not used"')
28
45
  response.headers.except!("X-Frame-Options")
29
46
  end
47
+
48
+ def deduced_phishing_attack?(decoded_host)
49
+ sanitized_host = ShopifyApp::Utils.sanitize_shop_domain(decoded_host)
50
+ if sanitized_host.nil?
51
+ message = "Host param for redirect to embed app in admin is not from a trusted domain, " \
52
+ "redirecting to root as this is likely a phishing attack."
53
+ ShopifyApp::Logger.info(message)
54
+ end
55
+ sanitized_host.nil?
56
+ end
30
57
  end
31
58
  end
@@ -27,7 +27,7 @@ module ShopifyApp
27
27
 
28
28
  unless has_payment
29
29
  if request.xhr?
30
- add_top_level_redirection_headers(url: confirmation_url, ignore_response_code: true)
30
+ RedirectForEmbedded.add_app_bridge_redirect_url_header(confirmation_url, response)
31
31
  ShopifyApp::Logger.debug("Responding with 401 unauthorized")
32
32
  head(:unauthorized)
33
33
  elsif ShopifyApp.configuration.embedded_app?
@@ -45,8 +45,16 @@ module ShopifyApp
45
45
  end
46
46
 
47
47
  def handle_billing_error(error)
48
- logger.info("#{error.message}: #{error.errors}")
49
- redirect_to_login
48
+ ShopifyApp::Logger.warn("Encountered billing error - #{error.message}: #{error.errors}\n" \
49
+ "Redirecting to login page")
50
+
51
+ login_url = ShopifyApp.configuration.login_url
52
+ if request.xhr?
53
+ RedirectForEmbedded.add_app_bridge_redirect_url_header(login_url, response)
54
+ head(:unauthorized)
55
+ else
56
+ fullpage_redirect_to(login_url)
57
+ end
50
58
  end
51
59
 
52
60
  def has_active_payment?(session)
@@ -16,6 +16,7 @@ module ShopifyApp
16
16
  end
17
17
 
18
18
  rescue_from ShopifyAPI::Errors::HttpResponseError, with: :handle_http_error
19
+ include ShopifyApp::WithShopifyIdToken
19
20
  end
20
21
 
21
22
  ACCESS_TOKEN_REQUIRED_HEADER = "X-Shopify-API-Request-Failure-Unauthorized"
@@ -53,7 +54,7 @@ module ShopifyApp
53
54
  @current_shopify_session ||= begin
54
55
  cookie_name = ShopifyAPI::Auth::Oauth::SessionCookie::SESSION_COOKIE_NAME
55
56
  load_current_session(
56
- auth_header: request.headers["HTTP_AUTHORIZATION"],
57
+ shopify_id_token: shopify_id_token,
57
58
  cookies: { cookie_name => cookies.encrypted[cookie_name] },
58
59
  is_online: online_token_configured?,
59
60
  )
@@ -78,13 +79,6 @@ module ShopifyApp
78
79
  response.set_header(ACCESS_TOKEN_REQUIRED_HEADER, "true")
79
80
  end
80
81
 
81
- def jwt_expire_at
82
- expire_at = request.env["jwt.expire_at"]
83
- return unless expire_at
84
-
85
- expire_at - 5.seconds # 5s gap to start fetching new token in advance
86
- end
87
-
88
82
  def add_top_level_redirection_headers(url: nil, ignore_response_code: false)
89
83
  if request.xhr? && (ignore_response_code || response.code.to_i == 401)
90
84
  ShopifyApp::Logger.debug("Adding top level redirection headers")
@@ -94,8 +88,8 @@ module ShopifyApp
94
88
  params[:shop] = if current_shopify_session
95
89
  current_shopify_session.shop
96
90
 
97
- elsif (matches = request.headers["HTTP_AUTHORIZATION"]&.match(/^Bearer (.+)$/))
98
- jwt_payload = ShopifyAPI::Auth::JwtPayload.new(T.must(matches[1]))
91
+ elsif shopify_id_token
92
+ jwt_payload = ShopifyAPI::Auth::JwtPayload.new(shopify_id_token)
99
93
  jwt_payload.shop
100
94
  end
101
95
  end
@@ -103,21 +97,12 @@ module ShopifyApp
103
97
  url ||= login_url_with_optional_shop
104
98
 
105
99
  ShopifyApp::Logger.debug("Setting Reauthorize-Url to #{url}")
106
- response.set_header("X-Shopify-API-Request-Failure-Reauthorize", "1")
107
- response.set_header("X-Shopify-API-Request-Failure-Reauthorize-Url", url)
100
+ RedirectForEmbedded.add_app_bridge_redirect_url_header(url, response)
108
101
  end
109
102
  end
110
103
 
111
104
  protected
112
105
 
113
- def jwt_shopify_domain
114
- request.env["jwt.shopify_domain"]
115
- end
116
-
117
- def jwt_shopify_user_id
118
- request.env["jwt.shopify_user_id"]
119
- end
120
-
121
106
  def host
122
107
  params[:host]
123
108
  end
@@ -273,10 +258,10 @@ module ShopifyApp
273
258
  online_token_configured?
274
259
  end
275
260
 
276
- def load_current_session(auth_header: nil, cookies: nil, is_online: false)
261
+ def load_current_session(shopify_id_token: nil, cookies: nil, is_online: false)
277
262
  return ShopifyAPI::Context.load_private_session if ShopifyAPI::Context.private?
278
263
 
279
- session_id = ShopifyAPI::Utils::SessionUtils.current_session_id(auth_header, cookies, is_online)
264
+ session_id = ShopifyAPI::Utils::SessionUtils.current_session_id(shopify_id_token, cookies, is_online)
280
265
  return nil unless session_id
281
266
 
282
267
  ShopifyApp::SessionRepository.load_session(session_id)
@@ -4,6 +4,11 @@ module ShopifyApp
4
4
  module RedirectForEmbedded
5
5
  include ShopifyApp::SanitizedParams
6
6
 
7
+ def self.add_app_bridge_redirect_url_header(url, response)
8
+ response.set_header("X-Shopify-API-Request-Failure-Reauthorize", "1")
9
+ response.set_header("X-Shopify-API-Request-Failure-Reauthorize-Url", url)
10
+ end
11
+
7
12
  private
8
13
 
9
14
  def embedded_redirect_url?
@@ -3,139 +3,109 @@
3
3
  module ShopifyApp
4
4
  module TokenExchange
5
5
  extend ActiveSupport::Concern
6
+ include ShopifyApp::AdminAPI::WithTokenRefetch
7
+ include ShopifyApp::SanitizedParams
8
+ include ShopifyApp::EmbeddedApp
6
9
 
7
- def activate_shopify_session
8
- if current_shopify_session.blank?
9
- retrieve_session_from_token_exchange
10
- end
10
+ included do
11
+ include ShopifyApp::WithShopifyIdToken
12
+ end
11
13
 
12
- if ShopifyApp.configuration.check_session_expiry_date && current_shopify_session.expired?
13
- @current_shopify_session = nil
14
- retrieve_session_from_token_exchange
15
- end
14
+ INVALID_SHOPIFY_ID_TOKEN_ERRORS = [
15
+ ShopifyAPI::Errors::MissingJwtTokenError,
16
+ ShopifyAPI::Errors::InvalidJwtTokenError,
17
+ ].freeze
18
+
19
+ def activate_shopify_session(&block)
20
+ retrieve_session_from_token_exchange if current_shopify_session.blank? || should_exchange_expired_token?
21
+
22
+ ShopifyApp::Logger.debug("Activating Shopify session")
23
+ ShopifyAPI::Context.activate_session(current_shopify_session)
24
+ with_token_refetch(current_shopify_session, shopify_id_token, &block)
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?
28
+ ensure
29
+ ShopifyApp::Logger.debug("Deactivating session")
30
+ ShopifyAPI::Context.deactivate_session
31
+ end
16
32
 
17
- begin
18
- ShopifyApp::Logger.debug("Activating Shopify session")
19
- ShopifyAPI::Context.activate_session(current_shopify_session)
20
- yield
21
- ensure
22
- ShopifyApp::Logger.debug("Deactivating session")
23
- ShopifyAPI::Context.deactivate_session
24
- end
33
+ def should_exchange_expired_token?
34
+ ShopifyApp.configuration.check_session_expiry_date && current_shopify_session.expired?
25
35
  end
26
36
 
27
37
  def current_shopify_session
28
- @current_shopify_session ||= begin
29
- session_id = ShopifyAPI::Utils::SessionUtils.current_session_id(
30
- request.headers["HTTP_AUTHORIZATION"],
31
- nil,
32
- online_token_configured?,
33
- )
34
- return nil unless session_id
35
-
36
- ShopifyApp::SessionRepository.load_session(session_id)
37
- end
38
+ return unless current_shopify_session_id
39
+
40
+ @current_shopify_session ||= ShopifyApp::SessionRepository.load_session(current_shopify_session_id)
38
41
  end
39
42
 
40
- def current_shopify_domain
41
- return if params[:shop].blank?
43
+ def current_shopify_session_id
44
+ @current_shopify_session_id ||= ShopifyAPI::Utils::SessionUtils.session_id_from_shopify_id_token(
45
+ id_token: shopify_id_token,
46
+ online: online_token_configured?,
47
+ )
48
+ end
42
49
 
43
- ShopifyApp::Utils.sanitize_shop_domain(params[:shop])
50
+ def current_shopify_domain
51
+ sanitized_shop_name || current_shopify_session&.shop
44
52
  end
45
53
 
46
54
  private
47
55
 
48
56
  def retrieve_session_from_token_exchange
49
- # TODO: Right now JWT Middleware only updates env['jwt.shopify_domain'] from request headers tokens,
50
- # which won't work for new installs.
51
- # we need to update the middleware to also update the env['jwt.shopify_domain'] from the query params
52
- domain = ShopifyApp::JWT.new(session_token).shopify_domain
53
-
54
- ShopifyApp::Logger.info("Performing Token Exchange for [#{domain}] - (Offline)")
55
- session = exchange_token(
56
- shop: domain, # TODO: use jwt_shopify_domain ?
57
- session_token: session_token,
58
- requested_token_type: ShopifyAPI::Auth::TokenExchange::RequestedTokenType::OFFLINE_ACCESS_TOKEN,
59
- )
60
-
61
- if session && online_token_configured?
62
- ShopifyApp::Logger.info("Performing Token Exchange for [#{domain}] - (Online)")
63
- session = exchange_token(
64
- shop: domain, # TODO: use jwt_shopify_domain ?
65
- session_token: session_token,
66
- requested_token_type: ShopifyAPI::Auth::TokenExchange::RequestedTokenType::ONLINE_ACCESS_TOKEN,
67
- )
68
- end
69
-
70
- ShopifyApp.configuration.post_authenticate_tasks.perform(session)
57
+ @current_shopify_session = nil
58
+ ShopifyApp::Auth::TokenExchange.perform(shopify_id_token)
71
59
  end
72
60
 
73
- def exchange_token(shop:, session_token:, requested_token_type:)
74
- if session_token.blank?
75
- # respond_to_invalid_session_token
76
- return
77
- end
78
-
79
- begin
80
- session = ShopifyAPI::Auth::TokenExchange.exchange_token(
81
- shop: shop,
82
- session_token: session_token,
83
- requested_token_type: requested_token_type,
84
- )
85
- rescue ShopifyAPI::Errors::InvalidJwtTokenError
86
- # respond_to_invalid_session_token
87
- return
88
- rescue ShopifyAPI::Errors::HttpResponseError => error
89
- ShopifyApp::Logger.error(
90
- "A #{error.code} error (#{error.class}) occurred during the token exchange. Response: #{error.response.body}",
91
- )
92
- raise
93
- rescue => error
94
- ShopifyApp::Logger.error("An error occurred during the token exchange: #{error.message}")
95
- raise
96
- end
97
-
98
- if session
99
- begin
100
- ShopifyApp::SessionRepository.store_session(session)
101
- rescue ActiveRecord::RecordNotUnique
102
- ShopifyApp::Logger.debug("Session not stored due to concurrent token exchange calls")
61
+ def respond_to_invalid_shopify_id_token
62
+ if request.headers["HTTP_AUTHORIZATION"].blank?
63
+ if missing_embedded_param?
64
+ redirect_to_embed_app_in_admin
65
+ else
66
+ redirect_to_bounce_page
103
67
  end
68
+ else
69
+ ShopifyApp::Logger.debug("Responding to invalid Shopify ID token with unauthorized response")
70
+ response.set_header("X-Shopify-Retry-Invalid-Session-Request", 1)
71
+ unauthorized_response = { message: :unauthorized }
72
+ render(json: { errors: [unauthorized_response] }, status: :unauthorized)
104
73
  end
105
-
106
- session
107
- end
108
-
109
- def session_token
110
- @session_token ||= id_token_header
111
74
  end
112
75
 
113
- def id_token_header
114
- request.headers["HTTP_AUTHORIZATION"]&.match(/^Bearer (.+)$/)&.[](1)
115
- end
76
+ def redirect_to_bounce_page
77
+ ShopifyApp::Logger.debug("Redirecting to bounce page for patching Shopify ID token")
78
+ patch_shopify_id_token_url =
79
+ "#{ShopifyAPI::Context.host}#{ShopifyApp.configuration.root_url}/patch_shopify_id_token"
80
+ patch_shopify_id_token_params = request.query_parameters.except(:id_token)
116
81
 
117
- def respond_to_invalid_session_token
118
- # TODO: Implement this method to handle invalid session tokens
82
+ bounce_url = "#{request.path}?#{patch_shopify_id_token_params.to_query}"
119
83
 
120
- # if request.xhr?
121
- # response.set_header("X-Shopify-Retry-Invalid-Session-Request", 1)
122
- # unauthorized_response = { message: :unauthorized }
123
- # render(json: { errors: [unauthorized_response] }, status: :unauthorized)
124
- # else
125
- # patch_session_token_url = "#{ShopifyAPI::Context.host}/patch_session_token"
126
- # patch_session_token_params = request.query_parameters.except(:id_token)
84
+ # App Bridge will trigger a fetch to the URL in shopify-reload, with a new session token in headers
85
+ patch_shopify_id_token_params["shopify-reload"] = bounce_url
127
86
 
128
- # bounce_url = "#{ShopifyAPI::Context.host}#{request.path}?#{patch_session_token_params.to_query}"
129
-
130
- # # App Bridge will trigger a fetch to the URL in shopify-reload, with a new session token in headers
131
- # patch_session_token_params["shopify-reload"] = bounce_url
87
+ redirect_to(
88
+ "#{patch_shopify_id_token_url}?#{patch_shopify_id_token_params.to_query}",
89
+ allow_other_host: true,
90
+ )
91
+ end
132
92
 
133
- # redirect_to("#{patch_session_token_url}?#{patch_session_token_params.to_query}", allow_other_host: true)
134
- # end
93
+ def missing_embedded_param?
94
+ !params[:embedded].present? || params[:embedded] != "1"
135
95
  end
136
96
 
137
97
  def online_token_configured?
138
98
  ShopifyApp.configuration.online_token_configured?
139
99
  end
100
+
101
+ def fullpage_redirect_to(url)
102
+ raise ShopifyApp::ShopifyDomainNotFound if current_shopify_domain.nil?
103
+
104
+ render(
105
+ "shopify_app/shared/redirect",
106
+ layout: false,
107
+ locals: { url: url, current_shopify_domain: current_shopify_domain },
108
+ )
109
+ end
140
110
  end
141
111
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyApp
4
+ module WithShopifyIdToken
5
+ extend ActiveSupport::Concern
6
+
7
+ def shopify_id_token
8
+ @shopify_id_token ||= id_token_from_request_env || id_token_from_authorization_header || id_token_from_url_param
9
+ end
10
+
11
+ def jwt_shopify_domain
12
+ request.env["jwt.shopify_domain"]
13
+ end
14
+
15
+ def jwt_shopify_user_id
16
+ request.env["jwt.shopify_user_id"]
17
+ end
18
+
19
+ def jwt_expire_at
20
+ expire_at = request.env["jwt.expire_at"]
21
+ return unless expire_at
22
+
23
+ expire_at - 5.seconds # 5s gap to start fetching new token in advance
24
+ end
25
+
26
+ private
27
+
28
+ def id_token_from_request_env
29
+ # This is set from ShopifyApp::JWTMiddleware
30
+ request.env["jwt.token"]
31
+ end
32
+
33
+ def id_token_from_authorization_header
34
+ request.headers["HTTP_AUTHORIZATION"]&.match(/^Bearer (.+)$/)&.[](1)
35
+ end
36
+
37
+ def id_token_from_url_param
38
+ params["id_token"]
39
+ end
40
+ end
41
+ end
@@ -2,16 +2,17 @@
2
2
 
3
3
  module ShopifyApp
4
4
  class JWTMiddleware
5
- TOKEN_REGEX = /^Bearer\s+(.*?)$/
5
+ TOKEN_REGEX = /^Bearer (.+)$/
6
+ ID_TOKEN_QUERY_PARAM = "id_token"
6
7
 
7
8
  def initialize(app)
8
9
  @app = app
9
10
  end
10
11
 
11
12
  def call(env)
12
- return call_next(env) unless authorization_header(env)
13
+ return call_next(env) unless ShopifyApp.configuration.embedded_app?
13
14
 
14
- token = extract_token(env)
15
+ token = token_from_authorization_header(env) || token_from_query_string(env)
15
16
  return call_next(env) unless token
16
17
 
17
18
  set_env_variables(token, env)
@@ -24,21 +25,24 @@ module ShopifyApp
24
25
  @app.call(env)
25
26
  end
26
27
 
27
- def authorization_header(env)
28
- env["HTTP_AUTHORIZATION"]
28
+ def token_from_authorization_header(env)
29
+ env["HTTP_AUTHORIZATION"]&.match(TOKEN_REGEX)&.[](1)
29
30
  end
30
31
 
31
- def extract_token(env)
32
- match = authorization_header(env).match(TOKEN_REGEX)
33
- match && match[1]
32
+ def token_from_query_string(env)
33
+ Rack::Utils.parse_nested_query(env["QUERY_STRING"])[ID_TOKEN_QUERY_PARAM]
34
34
  end
35
35
 
36
36
  def set_env_variables(token, env)
37
- jwt = ShopifyApp::JWT.new(token)
37
+ jwt = ShopifyAPI::Auth::JwtPayload.new(token)
38
38
 
39
+ env["jwt.token"] = token
39
40
  env["jwt.shopify_domain"] = jwt.shopify_domain
40
41
  env["jwt.shopify_user_id"] = jwt.shopify_user_id
41
42
  env["jwt.expire_at"] = jwt.expire_at
43
+ rescue ShopifyAPI::Errors::InvalidJwtTokenError
44
+ # ShopifyApp::JWT did not raise any exceptions, ensuring behaviour does not change
45
+ nil
42
46
  end
43
47
  end
44
48
  end
@@ -13,6 +13,7 @@ module ShopifyApp
13
13
  ]
14
14
 
15
15
  def initialize(token)
16
+ warn_deprecation
16
17
  @token = token
17
18
  set_payload
18
19
  end
@@ -60,5 +61,13 @@ module ShopifyApp
60
61
 
61
62
  payload
62
63
  end
64
+
65
+ def warn_deprecation
66
+ message = <<~EOS
67
+ "ShopifyApp::JWT will be deprecated, use ShopifyAPI::Auth::JwtPayload to parse JWT token instead."
68
+ EOS
69
+
70
+ ShopifyApp::Logger.deprecated(message, "23.0.0")
71
+ end
63
72
  end
64
73
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShopifyApp
4
- VERSION = "22.1.0"
4
+ VERSION = "22.2.0"
5
5
  end
data/lib/shopify_app.rb CHANGED
@@ -40,6 +40,9 @@ module ShopifyApp
40
40
 
41
41
  require "shopify_app/logger"
42
42
 
43
+ # Admin API helpers
44
+ require "shopify_app/admin_api/with_token_refetch"
45
+
43
46
  # controller concerns
44
47
  require "shopify_app/controller_concerns/csrf_protection"
45
48
  require "shopify_app/controller_concerns/localization"
@@ -53,9 +56,11 @@ module ShopifyApp
53
56
  require "shopify_app/controller_concerns/app_proxy_verification"
54
57
  require "shopify_app/controller_concerns/webhook_verification"
55
58
  require "shopify_app/controller_concerns/token_exchange"
59
+ require "shopify_app/controller_concerns/with_shopify_id_token"
56
60
 
57
61
  # Auth helpers
58
62
  require "shopify_app/auth/post_authenticate_tasks"
63
+ require "shopify_app/auth/token_exchange"
59
64
 
60
65
  # jobs
61
66
  require "shopify_app/jobs/webhooks_manager_job"
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shopify_app",
3
- "version": "22.1.0",
3
+ "version": "22.2.0",
4
4
  "repository": "git@github.com:Shopify/shopify_app.git",
5
5
  "author": "Shopify",
6
6
  "license": "MIT",
data/shopify_app.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.add_runtime_dependency("jwt", ">= 2.2.3")
20
20
  s.add_runtime_dependency("rails", "> 5.2.1")
21
21
  s.add_runtime_dependency("redirect_safely", "~> 1.0")
22
- s.add_runtime_dependency("shopify_api", ">= 14.1.0", "< 15.0")
22
+ s.add_runtime_dependency("shopify_api", ">= 14.3.0", "< 15.0")
23
23
  s.add_runtime_dependency("sprockets-rails", ">= 2.0.0")
24
24
 
25
25
  s.add_development_dependency("byebug")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_app
3
3
  version: !ruby/object:Gem::Version
4
- version: 22.1.0
4
+ version: 22.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-09 00:00:00.000000000 Z
11
+ date: 2024-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeresource
@@ -86,7 +86,7 @@ dependencies:
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: 14.1.0
89
+ version: 14.3.0
90
90
  - - "<"
91
91
  - !ruby/object:Gem::Version
92
92
  version: '15.0'
@@ -96,7 +96,7 @@ dependencies:
96
96
  requirements:
97
97
  - - ">="
98
98
  - !ruby/object:Gem::Version
99
- version: 14.1.0
99
+ version: 14.3.0
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
102
  version: '15.0'
@@ -314,6 +314,7 @@ files:
314
314
  - app/controllers/shopify_app/extension_verification_controller.rb
315
315
  - app/controllers/shopify_app/sessions_controller.rb
316
316
  - app/controllers/shopify_app/webhooks_controller.rb
317
+ - app/views/shopify_app/layouts/app_bridge.html.erb
317
318
  - app/views/shopify_app/partials/_button_styles.html.erb
318
319
  - app/views/shopify_app/partials/_card_styles.html.erb
319
320
  - app/views/shopify_app/partials/_empty_state_styles.html.erb
@@ -321,6 +322,7 @@ files:
321
322
  - app/views/shopify_app/partials/_layout_styles.html.erb
322
323
  - app/views/shopify_app/partials/_typography_styles.html.erb
323
324
  - app/views/shopify_app/sessions/new.html.erb
325
+ - app/views/shopify_app/sessions/patch_shopify_id_token.html.erb
324
326
  - app/views/shopify_app/shared/redirect.html.erb
325
327
  - config/locales/cs.yml
326
328
  - config/locales/da.yml
@@ -414,7 +416,9 @@ files:
414
416
  - lib/shopify_app/access_scopes/noop_strategy.rb
415
417
  - lib/shopify_app/access_scopes/shop_strategy.rb
416
418
  - lib/shopify_app/access_scopes/user_strategy.rb
419
+ - lib/shopify_app/admin_api/with_token_refetch.rb
417
420
  - lib/shopify_app/auth/post_authenticate_tasks.rb
421
+ - lib/shopify_app/auth/token_exchange.rb
418
422
  - lib/shopify_app/configuration.rb
419
423
  - lib/shopify_app/controller_concerns/app_proxy_verification.rb
420
424
  - lib/shopify_app/controller_concerns/csrf_protection.rb
@@ -428,6 +432,7 @@ files:
428
432
  - lib/shopify_app/controller_concerns/sanitized_params.rb
429
433
  - lib/shopify_app/controller_concerns/token_exchange.rb
430
434
  - lib/shopify_app/controller_concerns/webhook_verification.rb
435
+ - lib/shopify_app/controller_concerns/with_shopify_id_token.rb
431
436
  - lib/shopify_app/engine.rb
432
437
  - lib/shopify_app/errors.rb
433
438
  - lib/shopify_app/jobs/webhooks_manager_job.rb
@@ -476,7 +481,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
476
481
  - !ruby/object:Gem::Version
477
482
  version: '0'
478
483
  requirements: []
479
- rubygems_version: 3.5.7
484
+ rubygems_version: 3.5.9
480
485
  signing_key:
481
486
  specification_version: 4
482
487
  summary: This gem is used to get quickly started with the Shopify API