Is it true that simply generating a new expiring token will immeditaely invalidate a prior expiring token?
Becuase this is not how oauth works. Generating a new expiring token should NOT invalidate a prior token. The prior token should be invalidated by the actual expiring time.
Under this scenerio, how could we run 2 or more simulatenous processes on a single store without constantely checking if another processes hasn’t generated a new token? So before making every single call, we need to check if the token hasn’t been refreshed or not in the database?
The correct answer is simple - do not invalidate a token because a new token has been generated. That way each token is independent with its own independent expiry time.
Did I just read the docs wrong? It can’t possibly be implemented the wrong way right?
As I understand it, after you generate a new expiring token, the old expiring token will still work until its original expiration time.
So if I have tokens EXP1 and RFR1. EXP1 expires at 10:00:
At 9:50 I use RFR1 to get tokens EXP2 and RFR2. EXP2 will expire in one hour at 10:50
I can still use EXP1 between 9:50 and 10:00 to make API calls
At 10:00 I’ll get authentication errors if I use EXP1 and I’ll need to use EXP2
It does get tricky with multiple threads/processes though.
At a high level what we do is load token from the database when a process starts. Then we’ll make API calls with that token until we either get an authentication error or get close to the expiration time. Then we’ll use a database lock to make sure only one process can do the token exchange. This way we’re not querying the database before every query
Are you 100% sure, because I thought that I read in the docs - that generating a new expiring token expires the previous one - i should probably look this up again
Also the commenter above says that when you use it, it expires all other active tokens. But this is referring to non-expiring to expiring, right? I’m not referring to migration.
Can anyone seriuosly confirm when generating tokens from refresh tokens? Having 2 active expiring tokens should be possible, of course they will each expire on their own accord, but this must be allowed:
Its literally how oauth is implemented everywhere
Because there are situations where separate processes need separate valid tokens.
I’m not referring to migration from non-expiring to expiring.
I did read up about this, and seen mixed comments about having issues during the process.
Maybe some people aren’t doing it right, I’m not sure. But I’ve had to do something similar when rotating the private keys before so its probably a bit similar.
Hopefully we don’t have to stop the entire application during the migration, otherwise that would be a bad migration design. But this is not the same issue as I’m describing.
Actually I think you are right, From the docs:
How refresh token rotation works
Every refresh returns a new access token and a new refresh token. Store both securely, and use the new refresh token in the next refresh request.
Shopify doesn’t invalidate the refresh token your app presented at the moment it issues the replacement. The presented refresh token stays usable until the earliest of the following:
Your app uses the newer refresh token. Presenting it proves your app received it, so Shopify retires the previous one immediately. This is the normal case, and it happens on your app’s next refresh.
Your app acquires a new token. Token exchange and the authorization code grant retire every other refresh token for the app on the store right away.
30 days after your app first used that token to refresh. This caps how long an app that ignores the tokens it receives can keep refreshing from the same one.
The original 90-day expiry.
This rule here is ridiculous:
Your app uses the newer refresh token. Presenting it proves your app received it, so Shopify retires the previous one immediately. This is the normal case, and it happens on your app’s next refresh.
I’d recommend re-reading Shopify’s doc which explicitly answers the questions you’ve posed. Here’s the correct doc to reference:
when your app acquires a new one through token exchange or the authorization code grant, older expiring offline tokens for the same app and store are retired. Retired access tokens stay valid until their expires_in duration ends so in-progress requests can complete
Expiring offline access token | 1 hour (expires_in is 3600)
Hey all, just to corroborate what @Brett shared above - when your app acquires a new expiring token through token exchange or the authorization code grant, older expiring offline tokens for the same app and store are retired. A retired token still counts as valid until its own expires_in ends, so in-flight requests keep working. Two tokens with overlapping lifetimes are possible, and each expires on its own accord.
On lifetimes, the access token lasts 1 hour (expires_in: 3600). The 30 days figure is a different thing. The refresh token lasts 90 days, and each refresh returns a new one with a fresh 90-day expiry. If you keep using an old refresh token instead of the newest one, it stays usable until your app uses its replacement. That grace window is capped at 30 days from first use and never runs past the original 90 days. The token exchange docs outline this, and the standalone app guide shows the response shape.
We recommend always using the newest token pair for new requests, and retries with the same refresh token return the same rotated credentials.