This file documents important changes needed to upgrade your app's Shopify App version to a new major version.
This update moves API authentication logic from this gem to the shopify_api
gem.
- Delete
config/initializers/omniauth.rb
as apps no longer need to initializeOmniAuth
directly. - Delete
config/initializers/user_agent.rb
asshopify_app
will set the rightUser-Agent
header for interacting with the Shopify API. If the app requires further information in theUser-Agent
header beyond what Shopify API requires, specify this in theShopifyAPI::Context.user_agent_prefix
setting. - Remove
allow_jwt_authentication=
andallow_cookie_authentication=
invocations fromconfig/initializers/shopify_app.rb
as the decision logic for which authentication method to use is now handled internally by theshopify_api
gem, using theShopifyAPI::Context.embedded_app
setting. v19.0.0
updates theshopify_api
dependency to10.0.0
. This version ofshopify_api
has breaking changes. See the documentation for addressing these breaking changes on GitHub here.
Previously, we set the entire app user object in the session
object.
As of v19, since we no longer save the app user to the session (but only the shopify user id), we now store it as session[:shopify_user_id]
. Please make sure to update any references to that object.
Add a new handle
method to existing webhook jobs to go through the updated shopify_api
gem.
class MyWebhookJob < ActiveJob::Base
extend ShopifyAPI::Webhooks::Handler
class << self
# new handle function
def handle(topic:, shop:, body:)
# delegate to pre-existing perform_later function
perform_later(topic: topic, shop_domain: shop, webhook: body)
end
end
# original perform function
def perform(topic:, shop_domain:, webhook:)
# ...
The new shopify_api
gem offers a utility to temporarily create sessions for interacting with the API within a block.
This is useful for interacting with the Shopify API outside of the context of a subclass of AuthenticatedController
.
ShopifyAPI::Auth::Session.temp(shop: shop_domain, access_token: shop_token) do |session|
# make invocations to the API
end
Within a subclass of AuthenticatedController
, the current_shopify_session
function will return the current active
Shopify API session, or nil
if no such session is available.
The shopify_app
initializer must configure the ShopifyAPI::Context
. The Rails generator will
generate a block in the shopify_app
initializer. To do so manually, ensure the following is
part of the after_initialize
block in shopify_app.rb
.
Rails.application.config.after_initialize do
if ShopifyApp.configuration.api_key.present? && ShopifyApp.configuration.secret.present?
ShopifyAPI::Context.setup(
api_key: ShopifyApp.configuration.api_key,
api_secret_key: ShopifyApp.configuration.secret,
api_version: ShopifyApp.configuration.api_version,
host_name: URI(ENV.fetch('HOST', '')).host || '',
scope: ShopifyApp.configuration.scope,
is_private: !ENV.fetch('SHOPIFY_APP_PRIVATE_SHOP', '').empty?,
is_embedded: ShopifyApp.configuration.embedded_app,
session_storage: ShopifyApp::SessionRepository,
logger: Rails.logger,
private_shop: ENV.fetch('SHOPIFY_APP_PRIVATE_SHOP', nil),
user_agent_prefix: "ShopifyApp/#{ShopifyApp::VERSION}"
)
ShopifyApp::WebhooksManager.add_registrations
end
end
Version 18.1.2 replaces the deprecated EASDK redirect with an App Bridge 2 redirect when attempting to break out of an iframe. This happens when an app is installed, requires new access scopes, or re-authentication because the login session is expired.
To support Rails v6.1
, the SameSiteCookieMiddleware
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.
# same_site_cookie_middleware.rb
- cookie << '; SameSite=None' unless cookie =~ /;\s*samesite=/i
+ cookie << '; SameSite=None' if ShopifyApp.configuration.embedded_app?
By default, Rails v6.1
configures SameSite=Lax
on all cookies that don't specify this attribute.
Version 13.0.0 adds the ability to use both user and shop sessions, concurrently. This however involved a large change to how session stores work. Here are the steps to migrate to 13.x
- REMOVE
config.per_user_tokens = [true|false]
this is no longer needed - CHANGE
config.session_repository = 'Shop'
Toconfig.shop_session_repository = 'Shop'
- ADD (optional) User Session Storage
config.user_session_repository = 'User'
- CHANGE
include ShopifyApp::SessionStorage
toinclude ShopifyApp::ShopSessionStorage
- CHANGE if you are using shop sessions,
@shop_session
will need to be changed to@current_shopify_session
.
- CHANGE
session[:shopify]
is no longer set. Usesession[:user_id]
if your app uses user based tokens, orsession[:shop_id]
if your app uses shop based tokens.
ShopifyApp::LoginProtection
- CHANGE if you are using
ShopifyApp::LoginProtection#shopify_session
in your code, it will need to be changed toShopifyApp::LoginProtection#activate_shopify_session
- CHANGE if you are using
ShopifyApp::LoginProtection#clear_shop_session
in your code, it will need to be changed toShopifyApp::LoginProtection#clear_shopify_session
You do not need a user model; a shop session is fine for most applications.
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.
Add an API version configuration in config/initializers/shopify_app.rb
Set this to the version you want to run against by default. See Shopify API docs for versions available.
config.api_version = '2019-04'
You will need to add an api_version
method to your session storage object. The default implementation for this is.
def api_version
ShopifyApp.configuration.api_version
end
embedded_app.html.erb
the usage of shop_session.url
needs to be changed to shop_session.domain
<script type="text/javascript">
ShopifyApp.init({
apiKey: "<%= ShopifyApp.configuration.api_key %>",
shopOrigin: "<%= "https://#{ @shop_session.url }" if @shop_session %>",
debug: false,
forceRedirect: true
});
</script>
is changed to
<script type="text/javascript">
ShopifyApp.init({
apiKey: "<%= ShopifyApp.configuration.api_key %>",
shopOrigin: "<%= "https://#{ @shop_session.domain }" if @shop_session %>",
debug: false,
forceRedirect: true
});
</script>
You will need to also follow the ShopifyAPI upgrade guide to ensure your app is ready to work with API versioning.