Shopify App Warning Resurfaces: Your Guide to Fixing Deprecated Offline Tokens

Hey fellow Shopify app developers! It's me, your friendly Shopify migration expert, dropping in with some insights from the community. Lately, there's been some head-scratching around the re-emergence of that pesky "deprecated offline token" warning in the Shopify developer dashboard. If you've seen it pop up again, especially after a recent UI/UX refresh, you're not alone. This frustration was clearly articulated in a community thread started by @Iciren, who found the warning reappearing after initially resolving it. Let's dive into why this happens and how our community members tackled it.

Understanding the Persistent Warning

The core reason this warning keeps returning, as @v.marychenka highlighted, is that it counts API calls from the last 14 days. Even one stray call using an old, non-expiring token can bring it back. App installs only truly switch to the new, expiring token model once your app actively acquires and stores an expiring token pair. Stores that haven't opened your app since your initial fix might still be holding onto those old tokens, and any background calls from them will trigger the warning.

Screenshot of Shopify developer dashboard warning about deprecated offline token

Scenario 1: Existing Stores with Lingering Old Tokens

This is probably the most common culprit. You've updated your app's code, but not all your existing installations have "caught up" by interacting with your app in a way that triggers the token exchange. Here's how the community suggests you address it:

Proactive Token Exchange for Existing Installs

The most robust solution, as detailed by @v.marychenka, is to proactively exchange those old tokens for new, expiring ones for every single store. This involves making a specific API call. It's a bit of work, but it ensures you clear out those old tokens.

Here’s the step-by-step:

  1. For each of your installed shops, you'll need to send a POST request to their specific OAuth endpoint.
  2. The endpoint will look like this: https://{shop}.myshopify.com/admin/oauth/access_token
  3. Your POST request body should include the following parameters:
    • grant_type: Set this to urn:ietf:params:oauth:grant-type:token-exchange
    • client_id: Your app's client ID
    • client_secret: Your app's client secret
    • subject_token: The old, non-expiring access token you currently have stored for that shop.
    • subject_token_type: Set this to urn:shopify:params:oauth:token-type:offline-access-token
    • requested_token_type: Also set this to urn:shopify:params:oauth:token-type:offline-access-token
    • expiring: Set this to 1 (this is the magic flag that tells Shopify you want an expiring token pair).
  4. Important Note: Before rolling this out to all your production stores, test this process thoroughly on a development store. Once you successfully exchange and save the new token pair, the old token for that specific store becomes permanently invalid for GraphQL Admin API requests. So, make sure your update process is solid!

Framework-Specific Configuration Check

If you're using official Shopify app development frameworks like @shopify/shopify-app-remix or @shopify/shopify-app-react-router, there's a specific flag to ensure you're requesting expiring tokens. Double-check that the expiringOfflineAccessTokens flag is correctly set in your production shopifyApp() configuration. This is crucial for handling token acquisition correctly within these frameworks.

Scenario 2: New Installs Still Requesting Old Tokens

Sometimes, you fix the existing problem, but new issues crop up with new app installs. @Frec3 brought up an excellent point: if any part of your app's OAuth flow for a new install or reinstall isn't sending expiring=1, then those new stores will get non-expiring tokens. And guess what? The warning comes right back a couple of weeks later!

Actionable Check: Review your OAuth code grant process and any token exchange on first load. Ensure that the expiring=1 parameter is always included when requesting offline access tokens. You can also inspect the stored tokens for recently installed shops – if they lack a refresh token or an expiry date, it's a strong indicator that your new install flow is still requesting old-style tokens.

A More Comprehensive (and Drastic) Approach: Client Secret Rotation

For those feeling a bit overwhelmed by tracking down individual shops or if you're facing a similar situation to @bhavin_iflair, who couldn't identify which shop was causing the API calls, there's a more drastic but effective measure: rotating your app's client secret.

Bhavin's team decided to rotate their client secret for all shops. This involved converting all existing shop access tokens to use the new client secret and then deleting the old one. This essentially forces all connections to re-authenticate with the new secret, ensuring that all access tokens are re-issued under the correct, expiring model. It's like hitting a big "reset" button for your app's authentication across all stores. While it requires careful implementation to avoid downtime, it can be a clean way to ensure all tokens are brought up to date. You can usually find this option in your Shopify Partner Dashboard for your app settings.

Screenshot showing 'Rotate client secret' option in Shopify Partner Dashboard

Addressing Common Questions

"What if I don't migrate every single store immediately?"

As @Iciren wondered, if you don't perform a mass migration, tokens will eventually be replaced as stores open your app. The main impact is that the warning will likely persist until all those old tokens are retired or exchanged. Updating tokens in the future shouldn't be an issue, but the dashboard warning will remain a constant reminder until completion.

"Do I need a background task to keep tokens constantly valid for inactive stores?"

Expiring tokens are designed to refresh automatically on the next app visit or API call. For most apps, you don't need a dedicated background task just to keep them valid if there's no immediate use. If a store is truly inactive for more than 90 days, its expiring token might become invalid, but it will refresh upon their next visit. The warning is about the deprecated nature of old tokens, not about expired (but refreshable) new tokens.

Ultimately, getting rid of this warning is about ensuring all your app's installations are using the modern, expiring offline access tokens. It involves a combination of cleaning up old tokens for existing installs and making sure your new install flow is robust. The community discussion really highlighted how these nuances can cause a persistent headache, but with these strategies, you should be well-equipped to get that dashboard warning gone for good. Keep an eye on your logs, test thoroughly, and good luck!

Share:

Use cases

Explore use cases

Agencies, store owners, enterprise — find the migration path that fits.

Explore use cases