Implement authorization code grant manually
This tutorial shows you how to install your app and acquire access tokens using authorization code grant, either using a Shopify Admin API library, or from scratch. Using a Shopify Admin API library helps you to keep your app secure and reduce implementation time. We recommend that you use a library where possible.
What you'll learn
Anchor link to section titled "What you'll learn"After you've completed this tutorial, you'll be able to authorize a Shopify app using authorization code grant.
Requirements
Anchor link to section titled "Requirements"- You've created a Partner account.
- You've created an app that doesn't use a Shopify app template. These templates already have authorization code grant and sessions implemented.
- You have your app's client credentials.
- You're familiar with the authorization code grant flow in Shopify.
Step 1: Verify the installation request
Anchor link to section titled "Step 1: Verify the installation request"When a user installs your app through the Shopify App Store or using an installation link, your app receives a GET
request to the App URL path that you specify in the Partner Dashboard. The request includes the shop
, timestamp
, and hmac
query parameters. You need to verify the authenticity of these requests using the provided hmac
parameter.
All requests from Shopify contain the hmac
parameter. You should use this procedure to verify any future requests to your app.
To verify the request, you need to remove the hmac
parameter from the query string and process it through an HMAC-SHA256 hash function. For a request to be valid, the hmac
parameter must match the HMAC-SHA256 hash of the remaining parameters in the query string. These parameters are subject to change, so don't hard code them inside your verification code.
Remove the HMAC parameter from the query string
Anchor link to section titled "Remove the HMAC parameter from the query string"To remove the HMAC parameter, you can transform the query string to a key-value table, remove the hmac
key-value pair, and then transform your map back to a query string. The remaining parameters must be sorted alphabetically as strings, in the format "parameter_name=parameter_value"
.
Process the new string through a hash function
Anchor link to section titled "Process the new string through a hash function"You can process the string through an HMAC-SHA256
hash function using your client secret. The message is authentic if the generated hexdigest is equal to the value of the hmac
parameter.
The following Ruby example shows how to process the string through a hash function:
Step 2: Request authorization code
Anchor link to section titled "Step 2: Request authorization code"Before an app can access any store data, it needs to acquire an access token. Your app begins the process of acquiring an access token by redirecting the user through the authorization code flow and retrieving an authorization code.
Before issuing an authorization code, Shopify confirms that the user authorizes the permissions needed for your app. Depending on your app's configuration, the grant screen may display before or during your authorization code request. The following is an example of how the grant screen displays:
Your app should redirect the user through the authorization code flow if your app has verified the authenticity of the request and any of the following is true:
- Your app doesn't have a token for that shop.
- Your app uses online tokens and the token for that shop has expired.
- Your app has a token for that shop, but it was created before you rotated the app's secret.
- Your app has a token for that shop, but your app now requires scopes that differ from the scopes granted with that token.
Redirect to the authorization code flow
Anchor link to section titled "Redirect to the authorization code flow"To retrieve an authorization code, you need to perform a redirect. However, you can't perform a redirect from inside an iframe in the Shopify admin, due to X-Frame-Options: DENY
restrictions on Shopify admin pages. As a result, you need to perform the following additional steps to redirect to the grant screen if your app can be embedded:
If your app is never embedded, then perform a 3xx redirect to the grant screen.
If your app can be embedded:
- Check whether the app is being rendered in an iframe by checking the
embedded
parameter. - If the app is being rendered in an iframe, then escape the iframe using a Shopify App Bridge redirect action that redirects back to the same URL.
- Perform a 3xx redirect to the grant screen.
- Check whether the app is being rendered in an iframe by checking the
Check for and escape the iframe (embedded apps only)
Anchor link to section titled "Check for and escape the iframe (embedded apps only)"Check your request query parameters for an
embedded
parameter.If the parameter is present and has a value of
1
, then the request is being rendered in an iframe, and you should continue to the next step.If the parameter isn't present, or has a value of
0
, then the request isn't being rendered in an iframe. Use a 3xx redirect to redirect the user to the grant screen.If
embedded=1
, then render a page that uses the Shopify App Bridge redirect action to redirect back to the same URL. This breaks your app out of the iframe so that you can redirect to the grant screen.
The Shopify App Bridge redirect action will only work if it's loaded in an iframe. You should only use it when embedded=1
.
For an example implementation of this flow, refer to this page in the Node app template. This code uses a redirectUri
parameter, which represents the location to redirect to after Shopify App Bridge escapes the iframe. To understand how this parameter is defined, refer to this function in the Node app template.
Redirect using a 3xx redirect
Anchor link to section titled "Redirect using a 3xx redirect"If your app doesn't need to escape the iframe because it isn't embedded, or the embedded
parameter's value isn't 1, then you can redirect to the grant screen using a 3xx redirect.
The grant screen uses a URL with a specific format. When the user arrives at the URL, Shopify shows the grant screen to receive authorization from the user.
If you're using a Shopify Admin API library, then you can use a method from the library to construct the redirect URL and set a signed cookie. Later, your app will check the cookie to verify that the same browser initiated the OAuth request.
If you aren't using a library, then do the following:
Build a URL using the following format and parameters:
Query parameter Description {shop}
The name of the user's shop. {client_id}
The client ID for the app. {scopes}
A comma-separated list of scopes. For example, to write orders and read customers, use scope=write_products,read_shipping
. You should include every scope your app needs, regardless of any previously requested scopes. Any permission to write a resource includes the permission to read it. Be careful about what scopes you request. Some data is considered protected customer data, and places additional requirements on your app. For more information, refer to Protected customer data. This parameter should be omitted if you've pushed requested API access scopes with theTOML
file.{redirect_uri}
The URL to which a user is redirected after authorizing the app. The complete URL specified here must be added to your app as an allowed redirection URL, as defined in the Partner Dashboard. {nonce}
A randomly selected value provided by your app that is unique for each authorization request. During the OAuth callback, your app must check that this value matches the one you provided during authorization. This mechanism is important for the security of your app. {access_mode}
Sets the access mode. For an online access token, set to per-user
. For an [offline access token],(/docs/apps/build/authentication-authorization/access-tokens/offline-access-tokens) omit this parameter.3xx redirect to the URL. During the redirect, set a signed cookie with the
nonce
value from the URL.
Step 3: Validate authorization code
Anchor link to section titled "Step 3: Validate authorization code"After processing your request, Shopify redirects the user to your app's server. The following example demonstrates how the authorization_code
is passed in the redirect:
Security checks
Anchor link to section titled "Security checks"Before you continue, make sure that your app performs the following security checks to validate the OAuth callback. If any of the checks fail, then your app must reject the request with an error and not continue.
If you're using a Shopify Admin API library, then you can use a method from the library to perform the security checks:
If you aren't using a library, then make sure that you verify the following:
- The
nonce
is the same one that your app provided to Shopify when asking for permission. Additionally, the signed cookie that you set when asking for permission is present and its value equals thenonce
value in thestate
parameter. - The
hmac
is valid and signed by Shopify. - The
shop
parameter is a valid shop hostname, ends withmyshopify.com
, and doesn't contain characters other than letters (a-z), numbers (0-9), periods, and hyphens.
You can use a regular expression to confirm that the hostname is valid. In the following example, the regular expression matches the hostname form of https://{shop}.myshopify.com/
:
To match for the hostname form {shop}.myshopify.com
, you can use the following regular expression:
Step 4: Get an access token
Anchor link to section titled "Step 4: Get an access token"If all security checks pass, then you can exchange the authorization code from the confirmation redirect for an access token by sending a request to the shop’s access_token
endpoint:
In your request, {shop}
is the name of the user's shop and following parameters must be provided in the request body:
Parameter | Description |
---|---|
client_id |
The client ID for the app, as defined in the Partner Dashboard. |
client_secret |
The client secret for the app, as defined in the Partner Dashboard. |
code |
The authorization code provided in the redirect. |
The server responds with an online access token or an offline access token, as specified.
The following values are returned:
Value | Description |
---|---|
access_token |
An API access token that can be used to access the shop’s data as long as your app is installed. Your app should store the token somewhere to make authenticated requests for a shop’s data. An offline access token can be used for as long as the app is installed. |
scope |
The list of access scopes that were granted to your app and are associated with the access token. |
Confirm the requested scopes
Anchor link to section titled "Confirm the requested scopes"Due to the nature of OAuth, it’s possible for an app user to change the requested scope in the URL during the authorize phase, so the app should ensure that all required scopes are granted before using the access token.
If you requested both the read and write access scopes for a resource, then check only for the write access scope. The read access scope is omitted because it’s implied by the write access scope. For example, if your request included scope=read_orders,write_orders
, then check only for the write_orders
scope.
Online access mode
Anchor link to section titled "Online access mode"If an online access token was requested when redirecting to the grant screen, then the server responds with an access token and additional data:
The following values are returned:
Value | Description |
---|---|
access_token |
An API access token that can be used to access the shop’s data. Your app should store the token somewhere to make authenticated requests for a shop’s data. An online access token can be used for as long as the app is installed or for the next 24 hours, whichever comes first. After 24 hours, you need to refresh the access token. |
scope |
The list of access scopes that were granted to your app and are associated with the access token. |
expires_in |
The number of seconds until the access token expires. |
associated_user_scope |
The list of access scopes that were granted to the app and are available for this access token, given the user’s permissions. |
associated_user |
Information about the user who completed the OAuth authorization flow. The email field in this response appears regardless of the email verification status. If you’re using emails as an identification source, then make sure that the email_verified field is also true . You can use the id field to uniquely identify a single user. |
Step 5: Redirect to your app's UI
Anchor link to section titled "Step 5: Redirect to your app's UI"After you get an access token, you should redirect users to your app's UI. The method that you use depends on whether your app is embedded.
If your app is embedded, and the embedded
parameter isn't present or is equal to 0
, then you should 3xx
redirect to the embedded app URL. If your app is never embedded, or embedded=1
, then you should 3xx
redirect to your app URL.
The following code is an example implementation of the redirect logic:
If you redirect to your app URL, then make sure to include the shop
and host
parameters. Without these parameters, App Bridge can't initialize and your UI can't get a session token.
Because the embedded app URL might change in future, your app should construct the URL using Shopify Admin API libraries. If this isn't possible, then you can construct the embedded app URL manually using the following format:
Step 6: Make authenticated requests
Anchor link to section titled "Step 6: Make authenticated requests"After your app has obtained an API access token, it can make authenticated requests to the GraphQL Admin API. These requests are accompanied with a header X-Shopify-Access-Token: {access_token}
where {access_token}
is replaced with the acquired access token.
The following example shows how to retrieve a list of products using the GraphQL Admin API.
An authenticated request might fail in the following situations:
- Your app is requesting data that isn't permitted by the scope of the
access_token
. - Your app uses online tokens and the
access_token
you're using has expired.
In these cases, the app should perform a 3xx
redirect to the grant screen. If your app can be embedded, then you might need to escape the iframe used to embed it before you can perform the redirect.
Manage Access Scopes
Anchor link to section titled "Manage Access Scopes"After the user has agreed to install your app, you might want to change the granted scopes. For example, you might want to request additional scopes if your integration requires access to additional data.
To change scopes, redirect the user to the app authorization link and request authorization of new permissions. If your app can be embedded, then you might need to escape the iframe used to embed it before you can perform the redirect.
In the URL above, {shop}
is the name of the user's shop and the oauth/authorize
link includes the required parameters.
This URL might change in the future. To avoid interruptions, you can construct the URL using a Shopify Admin API library.
- Learn how to configure a webhook for your app and manage webhooks for different API versions.
- Explore the Webhooks references and the GraphQL Admin API.