# OAuth

This guide walks you through the authorization process, described in greater detail by the [OAuth 2.0 specification](https://tools.ietf.org/html/rfc6749).

### Terminology <a href="#terminology" id="terminology"></a>

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**: ShopBase's REST API, which the client can use to read and modify shop data.
* **User**: A ShopBase account holder, usually a merchant. The user gives permission to a client to access shop data through the REST API.

### The OAuth flow <a href="#the-oauth-flow" id="the-oauth-flow"></a>

ShopBase uses OAuth 2.0's [authorization code grant flow](https://tools.ietf.org/html/rfc6749#section-4.1) to issue access tokens on behalf of users.

1. The merchant makes a request to install the app.
2. The app redirects to ShopBase to load the OAuth grant screen and requests the required scopes.
3. ShopBase 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 ShopBase including the `client_id`, `client_secret`, and `code`.
6. ShopBase returns the access token and requested scopes.
7. The app uses the token to make requests to the ShopBase API.
8. ShopBase returns the requested data.

![](/files/-LkMsEqv1ca_i2l5q_WB)

### Step 1: Get client credentials

You need to [retrieve an API key and secret key](/build-an-app/making-your-first-request/authentication/public-apps.md) to identify the client during the authorization process.

### Step 2: Ask for permission <a href="#step-2-ask-for-permission" id="step-2-ask-for-permission"></a>

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 ShopBase App Store include the `shop`, `timestamp`, and `hmac` query parameters. If your install link doesn't originate from the ShopBase App Store, then you need to provide the `shop`parameter yourself or implement other handling to get the user's shop.

{% hint style="info" %}
&#x20;You need to verify the authenticity of these requests via the provided HMAC. For more information, see *Verification*.
{% endhint %}

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

```
https://{shop}.onshopbase.com/admin/oauth/authorize?client_id={api_key}&scope={scopes}&redirect_uri={redirect_uri}
```

* `{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 a whitelisted redirection URL, as defined in the Partner Dashboard.

### Step 3: Confirm installation <a href="#step-3-confirm-installation" id="step-3-confirm-installation"></a>

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.

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

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 `hmac` is valid. The HMAC is signed by ShopBase as explained below, in [*Verification*](https://help.shopify.com/en/api/getting-started/authentication/oauth#verification).
* The `hostname` parameter [is a valid hostname](https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names), ends with `onshopbase.com`, and does not contain characters other than letters (a-z), numbers (0-9), dots, and hyphens.

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}.onshopbase.com/admin/oauth/access_token.json
```

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](https://help.shopify.com/en/api/getting-started/authentication/oauth/api-access-modes) 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": "john@example.com",
    "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.

{% hint style="warning" %}
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.
{% endhint %}

### Step 4: Making authenticated requests <a href="#step-4-making-authenticated-requests" id="step-4-making-authenticated-requests"></a>

After the client has obtained an API access token, it can make authenticated requests to the REST API. These requests must include the following headers:

* `X-ShopBase-Access-Token`: {access\_token}
* `X-ShopBase-Token-Secret`: {token\_secret}

Starting from May 21, 2025, the `X-ShopBase-Token-Secret` header is required for all API requests. For details on how to generate and manage your Token Secret, please refer to the [Manage Access from App to ShopBase section](https://developers.shopbase.com/build-an-app/making-your-first-request/authentication/public-apps#manage-access-from-app-to-shopbase).

### Update OAuth scopes <a href="#update-oauth-scopes" id="update-oauth-scopes"></a>

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](https://help.shopify.com/en/api/getting-started/authentication/oauth#step-2-ask-for-permission) and request authorization of new permissions:

```
https://{shop}.onshopbase.com/admin/oauth/authorize
```

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

### Verification <a href="#verification" id="verification"></a>

Every request or redirect from ShopBase to the client server includes an `hmac` parameter that can be used to verify the authenticity of the request from ShopBase. 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:

```
code=0907a61c0c8d55e99db179b68161bc00&hmac=700e2dadb827fcc8609e9d5ce208b2e9cdaab9df07390d2cbca10d7c328fc4bf&shop=some-shop.onshopbase.com&timestamp=1337178173
```

{% hint style="warning" %}
This query string is merely an example, and the request parameters provided by ShopBase could be subject to change. Your verification strategy should not depend on the parameters in the example above.
{% endhint %}

#### Remove the HMAC <a href="#remove-the-hmac" id="remove-the-hmac"></a>

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:

```
code=0907a61c0c8d55e99db179b68161bc00&shop=some-shop.onshopbase.com&timestamp=1337178173
```

#### Process through the hash function <a href="#process-through-the-hash-function" id="process-through-the-hash-function"></a>

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

You can view [SampleApp example](https://bitbucket.org/brodev/sbase-sampleapp/src/72b8c49a65221bdf7dcd39d85bca853effd66847/backend/controllers/auth.js#lines-16) or below example in Ruby code.

**Ruby Example:**

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

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

Note: The HMAC verification procedure for OAuth is different from the procedure for verifying webhooks. To learn more about HMAC verification for webhooks, see [*Using webhooks*](/build-an-app/making-your-first-request/using-webhooks.md).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.shopbase.com/build-an-app/making-your-first-request/authentication/oauth.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
