---
gid: 5644b62f-fdb4-48d8-be39-32704b790be6
title: Set up embedded app authorization
description: Learn how authentication and authorization works for an embedded app in the Remix template.
---
This tutorial guides you through the process of implementing your own authorization flow for an embedded app that is not created using our
[Remix](/docs/apps/build/scaffold-app) app template.
It provides high-level information on each step necessary for your app to handle auth:
* Configuring access scopes through the CLI for Shopify to manage your app's installation on stores.
* Retrieving and validating session tokens to authenticate a user.
* Exchanging the session token for API access tokens to make API queries.
* Post authorization tasks.
## Configure access scopes through the CLI
The [Shopify CLI](https://shopify.dev/docs/apps/tools/cli) is a command-line interface tool to help you build Shopify apps.
It helps developers building new apps by providing app templates, it also has tools for existing apps to preview their app in a
development store, and manage app deployments and extensions.
#### Shopify managed install
If you haven't done so yet, follow the guide to [migrate your app to use Shopify CLI 3.x](https://shopify.dev/docs/apps/tools/cli/migrate).
This is important because it configures your app on Shopify so that Shopify can [manage installation of your app](https://shopify.dev/docs/apps/auth/installation)
instead of your app manually implementing the installation and authorization flow.
###### After completion of this step, you would have:
1. A `shopify.app.toml` file in your project directory.
2. Your app listed in your [Partner's dashboard](https://www.shopify.com/partners) so that you can configure other aspects of your app.

3. Your app can be started through the Shopify CLI, it can be installed to your test dev store, and can be seen loaded as an embedded app after installation.
```terminal
shopify app dev
```
#### Requesting and updating access scopes
##### App installation
The access scopes configured in the app TOML file are registered on Shopify, and the installation of your app is managed by Shopify.
When a user attempts to install your app, they will be asked to approve the access scopes that were configured in your TOML file.
Your app will not be loaded during the install process, but will only load after the user agrees to install the app.
Ensure you have `scopes` set in your TOML file, and `use_legacy_install_flow` is either removed or set to `false`.
[Learn more about Shopify API access scopes.](https://shopify.dev/docs/api/usage/access-scopes#authenticated-access-scopes)

##### Updating requested access scopes
Change your app's access scopes by editing the access scopes in the TOML file, and deploying the app again by running the following command:
```terminal
shopify app deploy
```
After your new app config has been deployed, users accessing your app will see a prompt to grant the extra access scope for your app.

## Authentication
Authentication is the process of verifying the identity of the user or the app. All apps that connect with Shopify APIs must authenticate the user before
making API requests. Embedded apps must authenticate their incoming requests with [session tokens](https://shopify.dev/docs/apps/auth/session-tokens).
### Retrieving session token
When the embedded app is loaded through Shopify admin, a [session token](https://shopify.dev/docs/apps/auth/session-tokens)
must be retrieved to validate that the user is authenticated. Session tokens are short lived, and must not be used
as a way for tracking session persistence. Session tokens must not be used after expiring. Always fetch the latest session token from the request header when handling requests.
#### The session token is available in 2 places:
* [Session token in the request header](#session-token-in-the-request-header)
* [Session token in the URL parameter](#session-token-in-the-url-parameter)
### Session token in the request header
You must use [App Bridge](https://shopify.dev/docs/api/app-bridge-library) to get session tokens to
verify the requests that are coming from your app's frontend in your app's backend. If App Bridge script is properly setup,
it'll append a new header field `authorization` to your server requests automatically.
When you have the App Bridge script tag set up in your front-end and it makes `fetch` requests to your backend,
the request's header will contain the session token field with the `authorization` key.
In the following example, the session token is `encoded_session_token`.
```json title="Example request headers"
{
...
"authorization": "Bearer encoded_session_token",
"accept-language": "...",
"accept-encoding": "...",
"accept": "*/*",
"user-agent": "...",
"host": "...",
...
}
```
If you created your app using the [Shopify Remix App Template](https://github.com/Shopify/shopify-app-template-remix),
then your app is already set up with App Bridge.
### Session token in the URL parameter
When Shopify admin loads your app path, it will automatically append the current user's session token to the URL path.
In the example below, when Shopify loads your app's path `my-app-path`, the following parameters are available in the URL.
```text title="Request URL Path"
/my-app-path?embedded=1&hmac={HMAC_VALUE}&host={HOST}&id_token={ID_TOKEN}&locale=en&session={SESSION}&shop={SHOP}×tamp={TIMESTAMP}
```
The encoded session token can be retrieved from the parameter field `id_token`.
There may not always be a session token in the URL because it might be lost or invalidated in server side redirects.
It's recommended that you still have a fallback [bounce page to get a session token from App Bridge](#bounce-page-to-get-a-session-token-from-app-bridge).
### Bounce page to get a session token from App Bridge
A bounce page is used to load the [App Bridge](https://shopify.dev/docs/api/app-bridge-library) script before redirecting back to
your app's requested path so that it contains information provided by App Bridge like [session token in the request header](#session-token-in-the-request-header).
It's a fallback method to get the session token if it's not available in the request header or the URL parameter.
An example bounce page implementation flow could be:
1. Add a bounce route that only renders an HTML response containing the App Bridge setup script. See the `/session-token-bounce` route in the example.
2. When the session token isn't available in the [request header](#session-token-in-the-request-header) or the [URL parameters](#session-token-in-the-url-parameter),
redirect to the bounce route from step 1.
When redirecting to the bounce page, you can use App Bridge' `shopify-reload` to reload your original route again after App Bridge
appends the session token information in the request header. See function `redirectToSessionTokenBouncePage` from the example.
To do this, you need to add a new parameter `shopify-reload` to your redirect bounce path, and it should contain the path you want to reload. The path should also contain the original parameters to your original path minus the `id_token` field. The `id_field`
must be removed because it might be stale by the time the redirect happens and it'll contain an invalid session token after the redirect.
### Validate the session token
After you obtain the session token from either the request header or URL parameters, decode and verify that the request is
made by an authenticated user.
You can use the [Shopify API](https://www.npmjs.com/package/@shopify/shopify-api) library package to avoid implementing your own method.
The library method `session.decodeSessionToken` throws an error if validation fails for this session token, indicating an invalid request,
and the user is not authenticated anymore. In which case, the request must not continue.
In cases when the session token has become invalid because app scopes have changed or it has expired, refresh the token in one of two ways. For a document request, redirect to the bounce page. For a an XHR request, send a `401 Unauthorized` response with the `X-Shopify-Retry-Invalid-Session-Request` header. App Bridge will intercept the request, refresh the session token, and retry the request once.
###### To learn more:
- [Shopify API JS library implementation of validation in `decodeSessionToken`](https://github.com/Shopify/shopify-app-js/blob/main/packages/apps/shopify-api/lib/session/decode-session-token.ts)
- [Shopify API JS library reference for `decodeSessionToken`](https://github.com/Shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/session/decodeSessionToken.md)
- [Anatomy of a session token](https://shopify.dev/docs/apps/auth/session-tokens#anatomy-of-a-session-token)
### Do's and don'ts for session tokens
Do:
- ✅ Validate session tokens on every request.
- ✅ Only continue request operation if session token is valid and active.
- ✅ Exchange the session token for an access token for API queries.
Don't:
- ❌ Use session tokens for session persistence, it's a short lived token that expires in 60 seconds.
- ❌ Depend on session token from the [URL params](#session-token-in-the-url-parameter) as your main validation method. It's ok for the initial server side rendering request, but subsequent
requests to your server should go through App Bridge and be validated through the session token from the [request header](#session-token-in-the-request-header).
## Authorization
Authorization is the process of giving permissions to apps. It begins when the user installs the app by granting a set of
permissions requested by the app. If you followed this guide, then your app is already configured to let
[Shopify manage your app installs](#requesting-and-updating-access-scopes).
The Next step is to obtain an access token to be used for making queries to Shopify APIs. There are 2 types of access tokens:
- [Online Access Tokens](https://shopify.dev/docs/apps/auth/access-token-types/online)
- [Offline Access Tokens](https://shopify.dev/docs/apps/auth/access-token-types/offline)
#### Token Exchange
We provide an authorization API to exchange a session token for an access token based on the
access scopes granted by the user from the [app's configuration](#requesting-and-updating-access-scopes).
We recommend using the [Shopify API](https://www.npmjs.com/package/@shopify/shopify-api) library package to avoid implementing your own token exchange method.
The library method `auth.tokenExchange` handles exchanging the session token for an access token that is used for making API queries.
Whether you use the library or implement your own API call to the token exchange endpoint,
you will receive an access token as a result of the exchange that can be used to make API queries.
###### To learn more:
- [Using the Token Exchange API to get access token](https://shopify.dev/docs/apps/auth/get-access-tokens/token-exchange/getting-started#step-2-get-an-access-token)
- [Token Exchange API overview](https://shopify.dev/docs/apps/auth/get-access-tokens/token-exchange)
- [Shopify API JS library implementation of `tokenExchange`](https://github.com/Shopify/shopify-app-js/blob/main/packages/apps/shopify-api/lib/auth/oauth/token-exchange.ts)
- [Shopify API JS library reference for `tokenExchange`](https://github.com/Shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/auth/tokenExchange.md)
- [Using access token to make queries to the Admin API](https://shopify.dev/docs/api/admin/getting-started)
### Do's and don'ts for access tokens
Do:
- ✅ Use a storage method to persist the access token retrieved from [token exchange](#token-exchange).
- ✅ Check for access token's existence or validity in session storage before performing another token exchange.
Don't:
- ❌ Perform token exchange on every request. Offline access tokens never expire and online access tokens expire after 24 hours, so token exchange should only happen when
the access token has expired or does not exist yet.
- ❌ Share the access token with others because they can make queries with this access token on behalf of your app.
## Post authorization tasks
Now that the app has a valid access token for the shop in which it was installed, it can use the access token to make authenticated API requests.
To make authenticated API queries to the Shopify Admin API, add your access token as a key to your request header `X-Shopify-Access-Token`,
see guide ["Getting started with the GraphQL Admin APIs"](https://shopify.dev/docs/api/admin/getting-started) for more details.
If this is a new install to a shop, you should perform the following tasks post authorization:
1. [Register and subscribe for relevant webhooks](#subscribing-to-webhooks) required by your app.
2. [Persist access token in storage](#session-storage) if it's not done already.
#### Subscribing to webhooks
[Webhooks](https://shopify.dev/docs/apps/webhooks) are useful for Shopify to notify your app when something changes in a shop.
Here is a list of [available webhook topics](https://shopify.dev/docs/api/admin-graphql/latest/enums/WebhookSubscriptionTopic).
If you created a Remix app from the Shopify CLI app templates, then your app will automatically register the default webhook `APP_UNINSTALLED` after installation.
It handles this APP_UNINSTALLED webhook to clean up session data from the database when an app is uninstalled.
See this [Remix guide on how to subscribe to webhooks](https://shopify.dev/docs/api/shopify-app-remix/latest/guide-webhooks).
If you're building your own app and want to subscribe to webhooks, you can use the access token retrieved after the initial installation to [register for webhooks](https://shopify.dev/docs/apps/webhooks/configuration).
#### Session storage
Don't exchange tokens on every request because it'll affect your app's performance. Online access tokens expires after
24 hours, and offline access tokens never expire. Thus the access token should be persisted after the exchange to be used by the app.
If you created a Remix app from the Shopify CLI app template, then your app will
automatically [store](https://github.com/Shopify/shopify-app-js/blob/8ab45fc547d5eefbf836b8722a7171f7f00bb1d2/packages/shopify-app-remix/src/server/authenticate/admin/strategies/token-exchange.ts#L61) and
[load](https://github.com/Shopify/shopify-app-js/blob/f143347361caf525def8137c53f8dbf634f87f27/packages/shopify-app-remix/src/server/authenticate/admin/authenticate.ts#L133-L135)
a session during the authentication/authorization process. The Remix template uses the [shopify-app-session-storage-prisma](https://shopify.dev/docs/api/shopify-app-remix/latest/entrypoints/shopifyapp#example-sessionstorage) library by default.
Shopify provides helpful wrapper libraries for session storage options,
you can see a [list of session storage options here](https://github.com/Shopify/shopify-app-js/tree/main?tab=readme-ov-file#session-storage-options).