Security update: offline token enforcement dates and new app security features
Public apps calling the Admin API must use expiring offline tokens by 1 January 2027; Shopify has also added client credentials access, IP allowlists and network access declarations.

- Published
- 2 Nov 2026
- Affects
- GraphQL Admin API, REST Admin API
What changed
On 27 October 2026, Shopify published a security update for app developers. It follows the 20 October post in which Shopify asked all app developers to secure their apps and said it would share more before any security change took effect.
The update does two things. It sets out an enforcement timeline for apps that have not moved to expiring offline access tokens, and it announces several new security features.
The migration deadline itself has not changed. All public apps that call the Admin API must migrate to expiring offline access tokens by 1 January 2027. Shopify says the new dates are for enforcement and are not extra time to migrate.
The new features Shopify lists are client credentials access, IP restrictions through an allowlist, network access declarations, identity verification for some installs, and an app security hub. The sources give no API version for any of these changes.
Who is affected
All public apps that call the Admin API are affected. If your public app still uses non-expiring offline access tokens, it has to move to expiring offline access tokens.
Not affected:
Custom apps
Merchant-created apps
Online access tokens
Enforcement timeline
If a public app that calls the Admin API has not migrated to expiring offline access tokens by 1 January 2027, Shopify will take the following steps. These dates apply to everyone, not only to apps that upgrade to a particular API version.
**1 January 2027:** the app is delisted from the Shopify App Store and blocked from new installs. Existing installs keep working.
**15 January 2027:** merchants using the app see a warning in Shopify admin.
**1 April 2027:** Admin API requests that use non-expiring offline access tokens return HTTP
403.
How to migrate
The steps depend on how your app requests tokens today. The migration guide says newly scaffolded apps already request expiring tokens.
Apps built from an app template
If your app uses @shopify/shopify-app-remix or @shopify/shopify-app-react-router, add the expiringOfflineAccessTokens flag to your shopifyApp() configuration and redeploy with shopify app deploy. The template then issues expiring tokens on new token exchanges, and stores and refreshes them for you.
Before
const shopify = shopifyApp({
// ...
});After
const shopify = shopifyApp({
// ...
future: {
expiringOfflineAccessTokens: true,
},
});Apps using token exchange or the authorization code grant
If you implement either flow yourself, add expiring=1 to your normal request. For the authorization code grant, that is the request that exchanges the code for an access token. Store the access_token and refresh_token from the response, along with expires_in and refresh_token_expires_in. Use the refresh token before expires_in seconds elapse. For token exchange, store the new refresh token each time and use that one next.
Before
curl -X POST \
https://{shop}.myshopify.com/admin/oauth/access_token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'client_id={client_id}' \
-d 'client_secret={client_secret}' \
-d 'code={authorization_code}'After
curl -X POST \
https://{shop}.myshopify.com/admin/oauth/access_token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'client_id={client_id}' \
-d 'client_secret={client_secret}' \
-d 'code={authorization_code}' \
-d 'expiring=1'Migrating existing installations directly
Existing installations migrate when your app acquires and stores an expiring token pair. If you don't want to wait for users to open your app, or your app is background-only (webhook consumers, app proxy backends, Flow actions), use the direct migration flow. It sends the stored non-expiring token and your client credentials to the same /admin/oauth/access_token endpoint, with no ID token or user session. The guide gives the required parameters: grant_type set to the token-exchange URN, subject_token as the non-expiring offline token, subject_token_type and requested_token_type both set to urn:shopify:params:oauth:token-type:offline-access-token, and expiring=1.
If you lose the response, repeat the same request with the original token and valid client credentials within seven days of the initial exchange. Eligible retries return the same token pair. Recovery stops once your app refreshes the issued pair or a later token acquisition for the same store retires it. If a retry returns invalid_subject_token, acquire a new token through ID-token exchange or the authorization code grant. Shopify returns 400 Bad Request with invalid_subject_token or invalid_requested_token_type when a parameter breaks the rules, for example if the subject token is an online token or already expires.
Handling errors during the transition
**403 Forbidden:** Shopify returns this when it rejects a request using a non-expiring offline token. The
errorsvalue containsNon-expiring access tokens are no longer accepted for the Admin API, followed by a migration link. Match on that phrase, not the whole string. A missing access scope also returns403, so check the message before re-authenticating.**Template apps:**
authenticate.admin(request)handles re-authentication automatically.**Token exchange:** catch the
403and re-run token exchange for a fresh token.**Authorization code grant:** catch the
403, clear the stored token, and send the merchant through the OAuth flow again.**401 Unauthorized with
{"error": "invalid_request"}:** this means a refresh token is expired, already replaced by one your app has since used, or otherwise invalid. Treat it as a signal to re-authenticate: the merchant must reopen your app in the Shopify admin to trigger a new token request.
New security features
The changelog says these features were rolled out in the week of the 27 October 2026 post. None of them has a stated deadline in the sources, and the sources give no API version for them.
Client credentials access
If your app loses a refresh token, your backend can request a new access token without waiting for a merchant to reopen the app. Your server signs a short-lived JSON Web Token, called a client assertion, with a private key that only your app holds. Shopify checks it against a public key you add in the Dev Dashboard. The client secret is not used in this flow.
Apps with public distribution can use this flow for any store that has installed them. Tokens are valid for up to one hour.
Other apps, such as custom apps, can get tokens only for stores in their organisation. Those tokens are valid for 24 hours.
Shopify accepts RS256 (RSA, 2048 to 8192 bits) and ES256 (EC, P-256) keys.
Each assertion must expire within 300 seconds of its issue time and carry a unique
jti. Sign a new one for every request, including retries.
The token request uses the client_credentials grant. The response contains no refresh token, so request a new access token when the current one nears expiry.
IP allowlist
An IP allowlist limits where your app's access tokens can be used. When enforcement is on, Shopify checks the source IP of every GraphQL Admin API and REST Admin API request that uses your tokens. Requests from outside your ranges fail with 403, as do requests whose source address Shopify cannot confirm.
Enter up to 100 addresses or CIDR ranges, one per line.
Use
/16or narrower for IPv4 and/32or narrower for IPv6. Use public addresses only, and start each range at its network address, such as203.0.113.0/24.If your servers reach Shopify over IPv6, include their IPv6 addresses.
It does not work with apps on platforms that assign dynamic IP addresses, such as most serverless platforms. It also does not work with tokens used by the Shopify Flow Send HTTP request action, or for GraphQL Admin API requests from a storefront hosted on Oxygen. Shopify rejects the Flow and Oxygen requests because it cannot confirm their source IP. The documentation says support for serverless platforms with dynamic IPs is coming soon, with no date.
Network access declarations
The new [network_access] section of shopify.app.toml lists the servers your app's code loads from or sends requests to, wherever it runs on a store. Shopify uses the list to spot requests your app did not make. You can also list sites you link customers to, so those links skip the warning customers normally see before leaving the store. The sources do not show the field names inside the section; check the app configuration documentation.
Identity verification and the security hub
Shopify now verifies your identity before installing apps on development and client-transfer stores. The changelog gives no further detail on how this works.
The new app security hub gives every app security practice its own page in the developer documentation, so you can check which practices apply to your app. Shopify also recommends running shopify app security check before every release.
What to do and deadline
The deadline for public apps that call the Admin API is 1 January 2027. By then they must be on expiring offline access tokens. The changelog says the later dates (15 January and 1 April 2027) are for merchants to prepare and are not extra time to migrate. The announcement date of 27 October 2026 is not a deadline.
Before then:
Check whether your app is public and still requests non-expiring offline tokens. If it is, migrate it using the method that matches how it gets tokens.
Check that your app handles a 403 on rejected requests and a 401 on refresh token errors, so it re-authenticates rather than failing silently.
If you set up an IP allowlist, run the test against recent traffic in the Dev Dashboard before you turn on enforcement. The test checks the last 30 days of your own addresses, and results can take a few minutes to include your latest requests.
The other new features (client credentials access, network access declarations, identity verification and the security hub) come with no deadline in the sources. The sources do not say whether any of them will become mandatory.
The sources give no API version for these changes, and none of them is described as an API version removal. The dates above are calendar dates set by Shopify.
Get the weekly digest
One email every Monday: what changed in Shopify, the deadlines coming up and what’s been announced, plus the week’s new guides. Free, and you can unsubscribe in one click.
Sources
- Security update: Offline token dates, new security features · Shopify · accessed 27 Oct 2026
- Migrate to expiring offline access tokens · Shopify developer docs · accessed 27 Oct 2026
- Get application-only access tokens for installed stores · Shopify developer docs · accessed 27 Oct 2026
- Restrict API access with an IP allowlist · Shopify developer docs · accessed 27 Oct 2026
AI-assisted, reviewed by Scott. Every claim is checked against the sources above.