OAuth

Your app cannot read Shopify data without authenticating first. It must get permission from a user before gaining access to any of the resources in the REST API. This guide will walk you through the authorization process (described in greater detail by the OAuth 2.0 specification).

Terminology

Before getting into the nitty-gritty of the authorization process, let’s go over some of the terms that we’ll be using for the rest of the guide.

  • Client
    Any application that would like access to a shop’s data. A user (usually the shop’s owner) must grant permission before the client can access any data.
  • API
    Shopify’s REST API. This is the place where the client can view and modify a shop’s data.
  • User
    A Shopify account holder, usually a shop owner. This is the person giving permission to a client to access their shop’s data through the REST API.

Step 1: Get the client’s credentials

You will need to retrieve an API Key and Shared Secret as the client uses them to identify itself during the authorization process.

To retrieve the credentials:

1. Click to open the Apps section of the Partners dashboard

2. Click the name of the App to view it's details:

Oauth shared secret x1

3. The API key is displayed for you, and you can click Show secret under the Credentials header to view the Shared secret.

Oauth shared secret

Step 2: Asking for permission

The first step of process is to get authorization from the user. This is done by displaying a prompt provided by Shopify:

Oauth app permissions

To show the prompt, redirect the user to this URL:

https://{shop}.myshopify.com/admin/oauth/authorize?client_id={api_key}&scope={scopes}&redirect_uri={redirect_uri}&state={nonce}

With these substitutions made:

  • {shop} - substitute this with the name of the user’s shop.
  • {api_key} - substitute this with the app’s API Key.
  • {scopes} - substitute this with a comma-separated list of scopes. For example, to write orders and read customers use scope=write_orders,read_customers.
  • {redirect_uri} - (Required) substitute this with the URL where you want to redirect the users after they authorize the client. The complete URL specified here must be identical to one of the Application Redirect URLs. Note: in older applications, this parameter was optional, and redirected to the Application Callback URL when no other value was specified.
  • {nonce} - a randomly selected value provided by your application, which is unique for each authorization request. During the OAuth callback phase, your application must check that this value matches the one you provided during authorization. This mechanism is important for the security of your application.

Step 3: Confirming installation

When the user clicks the Install button in the prompt, they will be redirected to the client server as specified above. One of the parameters passed in the confirmation redirect is the Authorization Code (the other parameters will be covered later in the guide).

https://example.org/some/redirect/uri?code={authorization_code}&hmac=da9d83c171400a41f8db91a950508985&timestamp=1409617544&state={nonce}&shop={hostname}

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

  • Ensure the provided nonce is the same one that your application provided to Shopify during the Step 2: Asking for permission.
  • Ensure the provided hmac is valid. The hmac is signed by Shopify as explained below, in the Verification section.
  • Ensure the provided hostname parameter is a valid hostname, ends with myshopify.com, and does not contain characters other than letters (a-z), numbers (0-9), dots, and hyphens.

If all security checks pass, the authorization code can be exchanged once for a permanent access token. The exchange is made with a request to the shop.

POST https://{shop}.myshopify.com/admin/oauth/access_token

With {shop} substituted for the name of the user’s shop and with the following parameters provided in the body of the request:

  • client_id
    The API Key for the app. (See the credentials section of this guide).
  • client_secret
    The Shared Secret for the app. (See the credentials section of this guide).
  • code
    The authorization code provided in the redirect described above.

The server will respond with an access token:

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

access_token is a permanent 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 is the list of access scope 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.

Step 4: Making authenticated requests

Now that 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.

Scopes

Part of the authorization process requires specifying which parts of a shop’s data the client would like access to (see the “Getting permission” part of this guide). A client can ask for any of the following scopes:

Delegating access to subsystems

Application developers may want to split their applications in multiple subsystems, each running on their own servers. With this type of architecture, a good practice is to avoid sharing a single access token between all the subsystems, and make sure each subsystem has access to only the minimal scopes it needs to function properly. It's better for security, but also makes access token rotation easier.

To create a new delegate access token, make an authenticated request to this endpoint:

POST https://{shop}.myshopify.com/admin/access_tokens/delegate

Provide the following parameters in the body of the request:

  • delegate_access_scope
    Required - The list of scopes that will be delegated to the new access token.
  • expires_in
    Optional - The amount of time, in seconds, after which the new access token is no longer be valid.

There are a few restrictions to take into account when creating a delegate access token:

  • An application can only delegate the same or fewer scopes than were granted to it when asking for permission. It's not possible to request extra scopes using this endpoint. If a new scope is required, the app must first be re-authorized with the new access scope by a user of the store.
  • When an application is re-authorized with fewer access scopes, all delegate access tokens will also lose the access scopes that are no longer authorized.
  • A delegate access token cannot be used to create new delegate access tokens.
  • Only an access token that never expires can be used to make authenticated requests to this endpoint.
  • A delegate access token can be used to make requests to any api endpoints that do not require access scopes. This includes, for example, uninstalling the application from a store. Make sure only trusted parties have access to a delegated access token.

Verification

Every request or redirect from Shopify to the client server includes an hmac parameter that can be used to ensure that it came from Shopify.

To verify that a request is valid, first parse the query string into a map of keys to values.

An example query string:

"code=0907a61c0c8d55e99db179b68161bc00&hmac=4712bf92ffc2917d15a2f5a273e39f0116667419aa4b6ac0b3baaf26fa3c4d20&shop=some-shop.myshopify.com&timestamp=1337178173"

Is converted to this map:

{
  "code": "0907a61c0c8d55e99db179b68161bc00",
  "hmac": "4712bf92ffc2917d15a2f5a273e39f0116667419aa4b6ac0b3baaf26fa3c4d20",
  "shop": "some-shop.myshopify.com",
  "timestamp": "1337178173"
}

Caution

This query string is merely an example, and the request parameters provided by Shopify could be subject to change at sometime in the future. Please ensure that your verification strategy is not dependent on the exact parameters in the example above.

HMAC Validation

The hmac entry is removed from the map, leaving the remaining parameters:

{
  "code": "0907a61c0c8d55e99db179b68161bc00",
  "shop": "some-shop.myshopify.com",
  "timestamp": "1337178173"
}

The characters & and % are replaced with %26 and %25 respectively in keys and values. Additionally the = character is replaced with %3D in keys.

Each key is concatenated with its value, separated by an = character, to create a list of strings. The list of key-value pairs is sorted lexicographically, and concatenated together with & to create a single string:

"code=0907a61c0c8d55e99db179b68161bc00&shop=some-shop.myshopify.com&timestamp=1337178173"

Lastly, this string processed through an HMAC-SHA256 using the Shared Secret as the key. The message is authentic if the generated hexdigest is equal to the value of the hmac parameter.

digest = OpenSSL::Digest.new('sha256')
secret = "hush"
message = "code=0907a61c0c8d55e99db179b68161bc00&shop=some-shop.myshopify.com&timestamp=1337178173"

digest = OpenSSL::HMAC.hexdigest(digest, secret, message)
digest == "4712bf92ffc2917d15a2f5a273e39f0116667419aa4b6ac0b3baaf26fa3c4d20"

Note

The HMAC verification procedure for OAuth is different from the procedure for verifying webhooks. To learn more about HMAC verification for webhooks, see the documentation for Using Webhooks.