Migrating from non expiring to expiring access tokens

So using application-only access for background tasks, we would no longer need to maintain the refresh-token and expiring access token (as a new pair is minted when merchant logs in to the app)?

Looking at the application only access pathway, it doesn’t seem that this gives a refresh token.

Correct - application-only access does not provide a refresh token.

Per the OAuth spec client credentials grant response SHOULD NOT respond with a refresh token. It’s also unnecessary since that client already has what it needs to acquire a new token once an old one has expired and a refresh token would be redundant.

So it means we no longer need to worry about refresh tokens at all?

Since we have a permanent (expiring) token generator installed on our servers with the private/public keypair?

I mean I love it, seems way easier to implement, but I wonder why wasn’t this announced from the start?

Thanks,
Peter

Becuase like many releases with Shopify recently, they didn’t take time to properly engineer and fully-think about what they release. The whole refresh thing was a smell in the first place.

Then they saw the community complaining and offered a better alternative.


My guess is that someone asked to rush this release to check the box KPI for security reached and put pressure on the dev team to release this quickly, because no sane engineer who’s smart enough to work at Shopify would have offered such a solution in the first place. I could be wrong but I wouldn’t be surprized I’m quite close to the truth.

My other guess is that Terence fought internally so we get a longer deadline and a better technical approach so he convinced whoever is the decision maker and compromised on the extended deadline, to get this better implementation. Once again I could be wrong, just my personal feeling after exchanging with Terence on this forum :slight_smile:

Since we have a permanent (expiring) token generator installed on our servers with the private/public keypair?

If your app exclusively uses application-only access to acquire tokens, you don’t need to use refresh tokens.

I mean I love it, seems way easier to implement, but I wonder why wasn’t this announced from the start?

OAuth supports several different grant types. For a long time, Shopify apps used only the authorization code grant. A few years ago, we introduced support for the token exchange grant alongside managed installation.

Apps already using these methods need a way to obtain new access tokens when their existing tokens expire. Refresh tokens are the standard OAuth mechanism for doing that. Previously, offline access tokens didn’t expire, so apps weren’t issued refresh tokens. To support migration, we also provide a way to exchange an existing non-expiring access token for a new access token and refresh token pair.

Last year, we added support for the client credentials grant, but only for apps built by merchants and installed on their own stores. We didn’t support partner apps—custom or public—using this method then, and we still don’t today. The primary reason is the risk associated with leaked credentials. If an app’s client ID and secret are exposed—for example, accidentally committed to a public repo—an attacker can use those credentials to acquire access tokens for stores where the app is installed and access merchant data. Because public apps can be installed on any merchant’s store, the potential impact is significant: the most popular public apps are installed on hundreds of thousands of stores.

While we’re confident that using refresh tokens to obtain new access tokens is safe and reliable, we’ve also heard developers’ concerns about implementing and managing this flow. That’s what led us to introduce application-only access this week. It gives apps a way to acquire tokens without merchant interaction, using a public/private key pair instead of a shared client secret. We’ve also been rolling out other security improvements, such as IP allowlisting, which works well with application-only access to provide complementary layers of protection for your app and merchant data.

Hi @TerenceShopify,

Thanks for your clarifications and for adding alternative way to recover access. Really appreciate it - it makes migration much safer!

Could you please also coordinate updates in Ruby libraries (shopify-api-ruby and shopify_app)? Both libraries still don’t support new application-only access tokens and we rely on them in our apps.

Yes, we have work in flight that will be updating our libraries. Should be shipping later today.

Just getting up to speed on this as we’ve intentionally put if off due to the various reasons/issues outlined here but this is one of the big concern we have.

As I understand it refreshing a shop’s token means taking an exclusive DB lock on a shop and making a network request :weary_cat:. This is not a good recipe for achieving high throughput. Our API client has built-in retries for fleeting network errors, rate limits, etc… which can result in the lock being held for even longer. Given this there is an argument to not hold the lock here, let the request fail, and another job will try but, either way, for high volume apps, this can have a huge impact on throughput, app responsiveness, and ultimately cost. Not necessarily Shopify’s problem. Their security concerns are no doubt valid.

The other thing I wonder about is user experience since the online access token only lasts 24 hours. A lot of product managers never want their users to be logged out. When I use Shopify I don’t have to login every 24 hours. Has anyone using these received negative feedback from users about excessive logins?

Actually no. I don’t think this will be possible since one token request can invalidate another’s. The lock is needed :frowning:

@sshaw did you notice the application only token? You can request muiltiple and they are valid for one hour and don’t invalidate previous ones

The other thing I wonder about is user experience since the online access token only lasts 24 hours. A lot of product managers never want their users to be logged out. When I use Shopify I don’t have to login every 24 hours. Has anyone using these received negative feedback from users about excessive logins?

The users will never notice if you implement it correctly. Your app just requests a new token before using it if it’s about to expire by using the refresh token.

Did anyone just get a “Complete your migration to expiring offline access tokens” email?

Everything within the email seems to be wrong. I completed the migration a while ago, and there’s no warnings/alerts for the app in the dev dashboard (they used to show there).

All I can think of is that these may be from dead or dormant customers who are no longer active, but never actually uninstalled the app. Really hope Shopify takes this into consideration before they delist their entire app store in January.

Hi,
I think this is a mistake. I also received this email, even though I have fully updated the tokens for all my customers.
Can anyone from Shopify confirm whether the last email was sent by mistake?

That raises a concern.. Do you need to explicitly migrate all stores in some way? Or simply not use the old offline tokens for 14 days ?

Also the email contains the numbers of stores “to migrate” but the number is higher than the actual number of stores we have in the database.

Also dev-only apps are being listed… What happens if we don’t migrate a dev app? Would it affect other apps in the same partner account?

I haven’t used an old permanent token in some time. The fact that the alert dropped off the Dev Dashboard seems to confirm that. The number of shops referenced in the email exceeds the numbers of active installs for my app listed in the dev dashboard. I think it is a mistake, but as is usual, it’s an arrogantly worded email from a do-not-reply email address. I’m glad that @Lyntest chimed in with similar behavior, hopefully others who have migrated can report in and we can further diagnose the issue.

Thanks @TerenceShopify , really appreciate your detailed reponse!

This is exactly my concern: my app is 8 year old and I have a plenty of dead stores I have not been able to migrate, all active ones have been migrated :expressionless:

we just received the email too, what’s worrying is that it’s stated one of our apps used an expired token in the last 14 days too, yet we’ve migrated off these months ago and nothing shows in the dev dashboard.

we do have a lot of dead stores which we weren’t able to migrate though, they haven’t been accessed and oauth fails when we try to manually migrate.

Exactly, we also removed from our database dead stores so we do not even have the old tokens to run the process in case…

I think the key point is that we must ensure all API calls use expiring tokens.

We proactively migrated all active stores that we actually access. However, in the Shopify Dev Console, we can still see many closed stores that we can not migrate.

  1. we even managed to migrate some, while others failed with the following errors:
  • 423 {"errors":"This store is unavailable"}

  • 403 {"errors":"Unavailable Shop"}

  1. We periodically clean up our database and remove closed stores (does not make sense to keep the data for a store closed two years ago for us).

If these stores are included in the migration requirements, this could be a major problem, as we have no way to migrate them.

However, I don’t think this should be an issue, since these stores won’t require any API access. Just in case a merchant reopens their store, they should go through a new installation flow and receive a new expiring token.

My understanding is that the requirement should apply to API calls made using active tokens, rather than the full list shown on dev dashboard.

@TerenceShopify can you confirm that scenario works?