Hi everyone,
I’m building an embedded Shopify app and I’m having an issue where the app automatically reloads the whole page and redirects to an exit-iframe URL whenever the access token or session is expired.
I’ll describe the behavior and what I want to achieve, and I’d really appreciate any guidance or best practices to handle this properly.
1. Current behavior (auto reload / exit-iframe)
When I open my app from the Shopify admin, if the access token is expired, the app doesn’t just fail the API call. Instead, the whole page “F5 reloads” and I see a URL like this:
https://admin.shopify.com/store/``<my-store>/apps/<my-app>/auth/exit-iframe?exitIframe=%2Fauth%3Fshop%3D<my-shop>.myshopify.com%26host%3D...
Decoded, that’s basically:
.../auth/exit-iframe?exitIframe=/auth?shop=<my-shop>.myshopify.com&host=...
So what’s happening is:
-
The app (or the Shopify auth middleware) detects that the session / access token is invalid or expired.
-
It triggers an exit-iframe redirect to
/authat the top-level. -
The browser reloads the entire app, goes through the OAuth/auth flow again, and then comes back.
From the user’s perspective, this looks like a sudden full-page reload just because the token expired.
2. What I would like to achieve
I understand that for initial OAuth and some security constraints (SameSite cookies, 3rd-party iframe, etc.), Shopify needs to use exit-iframe to run the auth flow in a top-level context.
However, I would like to:
-
Avoid this full-page reload / exit-iframe as much as possible in normal usage.
-
Preferably, when tokens expire, handle it in a way that doesn’t always kick the user out to
/authin a disruptive way.
In other words:
-
I’m OK with doing a top-level redirect for the very first install or when absolutely required.
-
But I don’t want the app to reload and go through
/authevery time a token/session expires, especially for common actions like just opening the app from the admin.
3. What I think is happening under the hood
From what I understand (please correct me if I’m wrong):
-
Shopify App Bridge / the auth middleware sees that there is no valid session or the access token has expired.
-
It then automatically responds with a redirect to
/auth. -
App Bridge detects this and uses the
exit-iframemechanism to open/authin the top-level window. -
/authstarts the OAuth flow again to get a new token. -
After that, it redirects back to the embedded app.
So from a high level, this is probably “correct” according to the standard templates, but it leads to a UX where the app keeps reloading when tokens expire.
4. My questions
I’m looking for best practices or recommended configuration to avoid or minimize this behavior:
-
Should I be using an offline access token for most of my backend API calls, so that I don’t need to re-authenticate the user frequently?
-
For example, using an offline token (non-expiring or expiring with refresh token) stored in my database, and:
-
Only using the OAuth flow when the app is first installed or when refresh fails.
-
Calling the Admin API / Partner API from the backend using the offline token, so the frontend doesn’t have to re-auth every time.
-
-
-
Should I fully switch to session tokens (JWT) for embedded app authentication, instead of relying on traditional cookie sessions?
-
So the frontend gets a short-lived session token on every load (via App Bridge),
and the backend validates that JWT and uses a long-lived offline access token for API calls. -
In that flow, when would
exit-iframestill be necessary? Only for the first install / when no offline token exists for that shop?
-
-
How should I configure my auth middleware so that:
-
It doesn’t redirect to
/authon every request, -
It only triggers
/auth(and thereforeexit-iframe) when:-
There is no stored offline token for that shop, or
-
The offline token + refresh token are truly invalid / revoked?
-
-
-
Is there any official Shopify example or documentation that shows:
-
A complete embedded app setup using:
-
Session tokens for frontend → backend auth, and
-
Offline access tokens for Shopify API calls,
-
-
In a way that avoids repeated
exit-iframeredirects when the user simply opens the app in admin?
-
5. My tech stack
-
Store:
<my-store>.myshopify.com -
App: Embedded app
-
Tech stack: [please fill in: Node.js / Next.js / PHP / Laravel / Ruby / etc.]
-
Auth libraries used: [please fill in: e.g.
@shopify/shopify-app-express,shopify-api-node, custom OAuth, etc.]
If it helps, I’m happy to share snippets of my:
-
/authand/auth/callbackroutes, and -
Auth middleware where I check the session / shop and potentially call the OAuth flow again.
6. Summary
-
Issue: When the user opens the embedded app and the access token/session is expired, the app automatically reloads the whole page and redirects via
exit-iframeto/authto get a new token. -
Goal: Reduce or avoid this disruptive reload behavior, by configuring auth correctly (offline tokens, session tokens, middleware logic, etc.).
-
Ask: Any official guidance, examples, or recommended patterns from Shopify or the community to handle this case cleanly?
Thanks in advance for any advice, links, or code examples!