Session Tokens And 401 Error

We’re in the final stages of publishing our embedded app to the Shopify App Store and are currently facing an issue related to session token validation and iframe loading.

i am using my own backend for OAuth, at backend
But my Remix embedded frontend app (created via shopify app) also expects to manage authentication via Shopify’s session token mechanism.

Since my Remix frontend doesn’t share sessions or validate tokens with my backend, it throws:
401 Unauthorized

  • We’ve built an eCommerce platform, and we are integrating Shopify to allow our vendors/merchants to connect their Shopify store and sync products and inventory.

  • Frontend (Admin Web App): React

  • Backend (API Server): Node.js/Express (MERN)

  • Shopify Integration:

    • We’ve implemented OAuth 2.0 manually on our backend (not using Shopify CLI or session tokens).
    • We handle all webhooks, product syncing, inventory, and store linkage server-side.
    • After installation, merchants are redirected back to our dashboard (or to the embedded app URL in Shopify).

What’s Working

  • App is embedded (embedded = true in shopify.web.toml)
  • OAuth flow completes successfully
  • Access tokens are securely stored and used for syncing
  • Shopify webhooks like app/uninstalled, products/create, etc. are configured and working
  • The app appears in the merchant’s Shopify admin under /admin/apps/{handle}

The Problem

When Shopify attempts to load the app via this iframe URL:
https://.trycloudflare.com/app?embedded=1&shop=test-store.myshopify.com&hmac=…

…we receive a 401 Unauthorized error, likely because:

  • The embedded Remix frontend created using shopify app expects session token-based authentication, but
  • We are handling OAuth and store validation entirely on our custom backend, and not using Shopify’s session token mechanism in the frontend.

As a result:

  • Shopify cannot validate the session in the frontend iframe request
  • The embedded app refuses to load (401), breaking the embedded experience
  • This blocks us from passing App Store submission checks

We do not want to manage OAuth in the frontend again — it’s already fully secured and validated in our backend.

We simply want our embedded app to:

  • Show a basic heading and merchant info inside the iframe
  • Work after the merchant installs the app and accesses it via /admin/apps/{handle}
  • Pass Shopify’s embedded app and App Bridge requirements

There’s probably some disjoint between your service providing the Shopify custom OAuth handshake and the embedded Remix app.

Why not just use managed installs by Shopify since these merchants will need to install your app through the Shopify app store anyway?

Then you can remove that custom OAuth and remove one less factor that could be contributing to this issue.

Hi there :waving_hand:

Please feel free to add additional context about you app set up if you think I may be misunderstanding.

A couple of things that may provide useful context

If you are using the Shopify App Remix template and using the await authenticate.admin(request) it will do a couple of things:

  • Authenticate that the request from your apps embedded frontend has been made by an authenticated user. This is a requirement for embedded apps. (Docs)
  • If the request is authenticated, it will attempt to load the access token from session storage for the shop.
  • If there is no session token available, then it will perform OAuth token exchange, to generate a new access token, and store it in session storage.

It sounds you might not want to use the authenticate.admin function with your set up. So you may need to handle some of this functionality on your own. This is a good tutorial on the requirements for authentication and oauth for embedded apps, that you can pull from.

To better understand exactly what is going wrong in the flow, I would recommend turning on debug level logging.

//shopify.server.ts
logger: {
level: 3
}

Something to keep in mind though:

We simply want our embedded app to:

  • Show a basic heading and merchant info inside the iframe

If you have an embedded app then you will need to be using session tokens to authenticate the request from your apps frontend, were made by an authenticated user. Regardless if you are using token exchange or auth code grant flow.

As suggested above, Shopify managed install, using Token Exchange install is our recommended installation flow, as it is the quickest and provides the best merchant experience. Both of which would be enabled by default in the Shopify Remix Template.

@Liz-Shopify @Dylan

we create an app manually and use the credentials for our backend project, user install the app by entering their domain and we then redirect them to shopify

in our web project user enter their domain
abc.myshopify.com

request go to backend with domain and their id

const shopifyUrl = ${ import.meta.env.VITE_BASE_URL }/shopify/auth?shop=${shopifyStoreDomain}&storeId=${user._id};
window.location.href = shopifyUrl;

at backend we collect the domain name and add other credentials and redirect them
https://${shop}/admin/oauth/authorize?client_id=${process.env.SHOPIFY_API_KEY}&scope=${process.env.SCOPES}&redirect_uri=${process.env.SHOPIFY_REDIRECT_URI}&state=${state}

now user can install our app and then he can connect their shopify store to our backend and his merchant account with the shopify store

Thats all what we want, but this method only work for our own development stores, we want to work with large no of shopify stores, you can say we only giving the access to connect the shopify store to our system,

for this process we publishing the app, we don’t need any embedded app for our workflow, but when publishing the app to shopify store some of the requirements are their which we may have to fullfill so for this fullfilment we doing the embedded app process, if we can skip this then its will very easier for us,

We want to work with many stores of shopify to connect with our system but without publish its not possible

and shopify team reply with verify technical words which we hard to understand