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 learning more about the details of the authorization process, make sure that you're familiar with some of the key terms that are used in this 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 secret key, which the client uses to identify itself during the authorization process.

To retrieve the client's credentials:

  1. Open the Apps section of the Partner Dashboard.

  2. Click the name of the app to view its details.

  3. Click App info.

  4. In the App credentials section, click the clipboard icon beside the API key field or the API secret key field to copy the credentials. The API key is displayed for you, and you can click Show next to API secret key to view the secret key.

Step 2: Ask for permission

The first step of the process is to get authorization from the user. Your app must begin this flow by receiving a GET request on the path specified as your 'app url' in the partner dashboard. Requests to this route from a user that is logged into the app store will include shop, timestamp, and hmac query parameters.

Requests do not need to originate from the app store as long as a shop parameter is present, or you are handling cases appropriately where one is not. Receiving authorization from the user is done by displaying a prompt provided by Shopify:

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}&grant_options[]={option}

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} - 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.
  • {option} - (Optional) Substitute this with the value per-user if you want to use the online access mode for API requests. Leave this parameter blank (or omit it) for offline access mode (default).

Step 3: Confirm 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 step 2.
  • 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, then 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 Secret Key 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 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 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.

Alternatively, the server will respond with an access token with additional data when online access mode is requested:

{
  "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": "john@example.com",
    "account_owner": true
  }
}

expires_in is the number of seconds until the access token expires.

associated_user_scope is the list of access scopes that were granted to the application and are available for this access token, given the user's permissions.

associated_user contains information about the user who went through the OAuth2 authorization flow.

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.

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.

An example query string:

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

The next step is to remove the hmac entry from the query string. A good way to do this is to transform the query string to a map, remove the hmac key-value pair, and then lexographically concatenate your map back to a query string. This leaves the remaining parameters:

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

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

An example in Ruby:

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

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

Sign up for a Partner account to get started.

Sign up