All Tutorials

Authenticate with OAuth

All Tutorials

Authenticate with OAuth

Authenticate with OAuth

Public apps and custom apps must authenticate using the OAuth 2.0 specification in order to use Shopify’s API resources.


Before learning more about the details of the authorization process, make sure that you’re familiar with some of the key terms used in this guide:

  • Client: Any app that wants access to a shop’s data. A user must grant permission before the client can access any data.
  • API: Shopify’s REST API, which the client can use to read and modify shop data.
  • User: A Shopify account holder, usually a merchant. The user gives permission to a client to access shop data through the REST API.

The OAuth flow

Shopify uses OAuth 2.0’s authorization code grant flow to issue access tokens on behalf of users.

Flowchart of the OAuth credential granting process

  1. The merchant makes a request to install the app.
  2. The app redirects to Shopify to load the OAuth grant screen and requests the required scopes.
  3. Shopify displays a prompt to receive authorization and prompts the merchant to login if required.
  4. The merchant consents to the scopes and is redirected to the redirect_uri.
  5. The app makes an access token request to Shopify including the client_id, client_secret, and code.
  6. Shopify returns the access token and requested scopes.
  7. The app uses the token to make requests to the Shopify API.
  8. Shopify returns the requested data.

Step 1: Get client credentials

You need to retrieve an API key and secret key to identify the client during the authorization process.

Step 2: Ask for permission

After the user clicks an install link, your app receives a GET request on the app URL path specified in the Partner Dashboard. Requests to this route from a user that is logged into the Shopify App Store include the shop, timestamp, and hmac query parameters. If your install link doesn’t originate from the Shopify App Store, then you need to provide the shop parameter yourself or implement other handling to get the user’s shop.

Shopify displays a prompt to receive authorization from the user:

Screenshot showing the Shopify OAuth installation permissions prompt

To show the prompt, redirect the user to the following URL with the query parameters defined below:

  • {shop}: The name of the user’s shop.
  • {api_key}: The app’s API Key.
  • {scopes}: A comma-separated list of scopes. For example, to write orders and read customers, use scope=write_orders,read_customers. Any permission to write a resource includes the permission to read it.
  • {redirect_uri}: The URL to which a user is redirected after authorizing the client. 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 access mode. Defaults to offline access mode if left blank or omitted. Set to per-user for online access mode.

Step 3: Confirm installation

When the user clicks the Install button in the prompt, they’re redirected to the client server as specified above. The authorization_code is passed in the confirmation redirect.{authorization_code}&hmac=da9d83c171400a41f8db91a950508985&host={base64_encoded_hostname}&timestamp=1409617544&state={nonce}&shop={shop_origin}

Before you continue, make sure your app performs the following security checks. If any of the checks fails, your app must reject the request with an error, and must not continue.

  • The nonce is the same one that your app provided to Shopify during step two.
  • The hmac is valid. The HMAC is signed by Shopify as explained below, in Verification.
  • The shop parameter is a valid shop hostname, ends with, and doesn't contain characters other than letters (a-z), numbers (0-9), dots, 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


    To match for the hostname form, you can use the following regular expression:


If all security checks pass, then you can exchange the access code for a permanent access token by sending a request to the shop’s access_token endpoint:

POST https://{shop}

In your request, {shop} is the name of the user’s shop and the following parameters must be provided in the request body:

  • client_id: The API key for the app, as defined in the Partner Dashboard.
  • client_secret: The API secret key for the app, as defined in the Partner Dashboard.
  • code: The authorization code provided in the redirect.

The server responds with an access token:

  "access_token": "f85632530bf277ec9ac6f649fc327f17",
  "scope": "write_orders,read_customers"

The following values are returned:

  • access_token: An API access token that can be used to access the shop’s data as long as the client is installed. Clients should store the token somewhere to make authenticated requests for a shop’s data.
  • scope: The list of access scopes that were granted to the application and are associated with the access token. Due to the nature of OAuth, it’s always possible for a merchant to change the requested scope in the URL during the authorize phase, so the application 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.

If online access mode is requested, then the server responds with an access token and additional data:

  "access_token": "f85632530bf277ec9ac6f649fc327f17",
  "scope": "write_orders,read_customers",
  "expires_in": 86399,
  "associated_user_scope": "write_orders",
  "associated_user": {
    "id": 902541635,
    "first_name": "John",
    "last_name": "Smith",
    "email": "",
    "email_verified": true,
    "account_owner": true,
    "locale": "en",
    "collaborator": false

The following values are returned:

  • 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.

Step 4: Making authenticated requests

After the client has obtained an API access token, it can make authenticated requests to the REST API. These requests are accompanied with a header X-Shopify-Access-Token: {access_token} where {access_token} is replaced with the permanent token.

Update OAuth scopes

After the user has agreed to install your app, you might want to change the granted scope. For example, you might want to request additional scopes if your integration requires access to other API endpoints.

To change scopes, redirect your users to the app authorization link and request authorization of new permissions:


In the URL, {shop} is the users myshopify domain and the oauth/authorize link includes the required parameters.


Every request or redirect from Shopify to the client server includes an hmac parameter that can be used to verify the authenticity of the request from Shopify. For each request, you must remove the hmac entry from the query string and process it through an HMAC-SHA256 hash function.

By way of example, consider the following query string:


IDs array parameter

If your query string includes an ids array parameter, then the query string is parsed so that ids[]=1&ids[]=2 gets converted to ids=["1", "2"] before the signature is generated.

Remove the HMAC

To remove the hmac, you can transform the query string to a map, remove the hmac key-value pair, and then lexicographically concatenate your map back to a query string. This leaves the remaining parameters from the example query string:


Process through the hash function

You can process the string through an HMAC-SHA256 hash function using the secret key. The message is authentic if the generated hexdigest is equal to the value of the hmac parameter.

Ruby Example:

digest =
secret = "hush"
message = "code=0907a61c0c8d55e99db179b68161bc00&"

digest = OpenSSL::HMAC.hexdigest(digest, secret, message)
ActiveSupport::SecurityUtils.secure_compare(digest, "700e2dadb827fcc8609e9d5ce208b2e9cdaab9df07390d2cbca10d7c328fc4bf")

Session tokens for embedded apps

If you're using Shopify App Bridge to embed your app in the Shopify Admin, then it's not recommended to use session cookies to authenticate the merchant to your app server. Instead, use session token authentication to obtain a JWT (JSON web token) from App Bridge.

After you've obtained the JWT, you can use it to look up session data. Using this approach, your app only needs to perform an OAuth redirect for the initial install, and doesn't need to store the user information in a cookie.

For more information, refer to Authenticate an embedded app using session tokens.