The Shopify App gem implements OAuth 2.0 to get session tokens. These are used to authenticate requests made by the app to the Shopify API.
By default, the gem generates an embedded app frontend that uses Shopify App Bridge to fetch session tokens. Session tokens are used by the embedded app to make authenticated requests to the app backend.
See Getting started with session token authentication to learn more.
⚠️ Be sure you understand the differences between the types of authentication schemes before reading this guide.
- Supported types of OAuth Flow
- Run jobs after the OAuth flow
- Rotate API credentials
- Making authenticated API requests after authorization
Tip
If you are building an embedded app, we strongly recommend using Shopify managed installation with token exchange instead of the authorization code grant flow.
- Token Exchange
- Recommended and is only available for embedded apps
- Doesn't require redirects, which makes authorization faster and prevents flickering when loading the app
- Access scope changes are handled by Shopify when you use Shopify managed installation
- Authorization Code Grant Flow
- Suitable for non-embedded apps
- Installations, and access scope changes are managed by the app
OAuth process by exchanging the current user's session token (shopify id token) for an access token to make authenticated Shopify API queries. This will replace authorization code grant flow completely when your app is configured with Shopify managed installation.
To enable token exchange authorization strategy, you can follow the steps in "New embedded app authorization strategy". Upon completion of the token exchange to get the access token, post authenticated tasks will be run.
Learn more about:
- How token exchange works
- Using Shopify managed installation
- Configuring access scopes through the Shopify CLI
If the access token used to make an API call is invalid, the token exchange strategy will handle the error and try to retrieve a new access token before retrying the same operation. See "Re-fetching an access token when API returns Unauthorized" section for more information.
If your access scopes are configured through the Shopify CLI, scope changes will be handled by Shopify automatically. Learn more about Shopify managed installation. Using token exchange will ensure that the access token retrieved will always have the latest access scopes granted by the user.
Authorization code grant flow is the OAuth flow that requires the app to redirect the user to Shopify for installation/authorization of the app to access the shop's data. It is still required for apps that are not embedded.
If your app is not using Shopify managed installation with declared scopes in your .toml
file, you can change the requested access scopes during OAuth flow
by adding the scope
to your configurations - ShopifyApp.configuration
& ShopifyAPI::Context.setup
.
# config/initializers/shopify_app.rb
ShopifyApp.configure do |config|
...
config.scope = ["read_discounts", "write_products"]
...
end
ShopifyAPI::Context.setup(
...
scope: ShopifyApp.configuration.scope,
...
)
To perform authorization code grant flow, you app will need to handle begin OAuth and OAuth callback routes.
ShopifyApp automatically redirects the user to Shopify to complete OAuth to install the app when the ShopifyApp.configuration.login_url
is reached.
Behind the scenes the ShopifyApp gem starts the process by calling ShopifyAPI::Auth::Oauth.begin_auth
to build the
redirect URL with necessary parameters like the OAuth callback URL, scopes requested, type of access token (offline or online) requested, etc.
The ShopifyApp gem then redirect the merchant to Shopify, to ask for permission to install the app. (See ShopifyApp::SessionsController.redirect_to_begin_oauth
for detailed implementation)
Shopify will redirect the merchant back to your app's callback URL once they approve the app installation.
Upon completing the OAuth flow, Shopify calls the app at ShopifyApp.configuration.login_callback_url
. (This was provided to Shopify in the OAuth begin URL parameters)
The default callback controller ShopifyApp::CallbackController
provides the following behaviour:
- Logging into the shop and resetting the session
- Storing the session to the
SessionRepository
- Post authenticate tasks
- Redirecting to the return address
If you need to define a custom callback controller to handle your app's use case, you can configure the callback route to your controller.
Example:
- Create the new custom callback controller
# web/app/controllers/my_custom_callback_controller.rb
class MyCustomCallbackController
def callback
# My custom callback logic
end
end
- Override callback routing to this controller
# web/config/routes.rb
Rails.application.routes.draw do
root to: "home#index"
# Overriding the callback controller to the new custom one.
# This must be added before mounting the ShopifyApp::Engine
get ShopifyApp.configuration.login_callback_url, to: 'my_custom_callback#callback'
mount ShopifyApp::Engine, at: "/api"
# other routes
end
When the OAuth process is completed, the created session has a scope
field which holds all of the access scopes that were requested from the merchant at the time.
When an app's access scopes change, it needs to request merchants to go through OAuth again to renew its permissions.
See Handling changes in access scopes.
After authentication is complete, a few tasks are run by default by PostAuthenticateTasks:
The PostAuthenticateTasks class is responsible for triggering the webhooks manager for webhooks registration, and enqueue jobs from after_authenticate_job.
If you simply need to enqueue more jobs to run after authenticate, use after_authenticate_job to define these jobs.
If your post authentication tasks is more complex and is different than just installing webhooks and enqueuing jobs,
you can customize the post authenticate tasks by creating a new class that has a self.perform(session)
method,
and configuring custom_post_authenticate_tasks
in the initializer.
# my_custom_post_authenticate_task.rb
class MyCustomPostAuthenticateTask
def self.perform(session)
# This will be triggered after OAuth callback and token exchange completion
end
end
# config/initializers/shopify_app.rb
ShopifyApp.configure do |config|
config.custom_post_authenticate_tasks = "MyCustomPostAuthenticateTask"
end
See ShopifyApp::AfterAuthenticateJob
.
If your app needs to perform specific actions after the user is authenticated successfully (i.e. every time a new session is created), ShopifyApp can queue or run a job of your choosing. To configure the after authenticate job, update your initializer as follows:
ShopifyApp.configure do |config|
config.after_authenticate_job = { job: "Shopify::AfterAuthenticateJob" }
end
The job can be configured as either a class or a class name string.
If you need the job to run synchronously add the inline
flag:
ShopifyApp.configure do |config|
config.after_authenticate_job = { job: "Shopify::AfterAuthenticateJob", inline: true }
end
We've also provided a generator which creates a skeleton job and updates the initializer for you:
bin/rails g shopify_app:add_after_authenticate_job
If you want to perform that action only once, e.g. send a welcome email to the user when they install the app, you should make sure that this action is idempotent, meaning that it won't have an impact if run multiple times.
If your Shopify secret key is leaked, you can use the RotateShopifyTokenJob
to perform API Credential Rotation.
Before running the job, you'll need to generate a new secret key from your Shopify Partner dashboard, and update the /config/initializers/shopify_app.rb
to hold your new and old secret keys:
config.secret = Rails.application.secrets.shopify_secret
config.old_secret = Rails.application.secrets.old_shopify_secret
Also make sure the old secret is specified when setting up ShopifyAPI::Context
as well:
ShopifyAPI::Context.setup(
api_key: ShopifyApp.configuration.api_key,
api_secret_key: ShopifyApp.configuration.secret,
# ...
old_api_secret_key: ShopifyApp.configuration.old_secret,
)
We've provided a generator which creates the job and an example rake task:
bin/rails g shopify_app:rotate_shopify_token_job
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.
strategy.options[:old_client_secret] = ShopifyApp.configuration.old_secret
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 toconfig/initializers/omniauth.rb
:
After the app is installed onto a shop and has been granted all necessary permission, a new session record will be added to SessionRepository#shop_storage
, or SessionRepository#user_storage
if online sessions are enabled.
When your app needs to make API requests to Shopify, ShopifyApp
's ActiveSupport
controller concerns can help you retrieve the active session token from the repository to make the authenticate API call.
⚠️ See Sessions page to understand how sessions work.⚠️ See Controller Concerns page to understand when to use which concern.