Refresh token returned with an expiry far shorter than the documented 90 days

Setup: App migrated from non-expiring offline access tokens to expiring offline access tokens, following the migration guide. Stack: Ruby on Rails, using shopify_app 23.0.2 and shopify_api 16.2.0.

Issue: For multiple shops, after calling grant_type=refresh_token against POST /admin/oauth/access_token, the refresh_token returned in the response appears to have an expiry far shorter than the documented 90-day lifetime.

Timestamps (JST) — example from one of the affected shops:

Refresh call made at (approx.):          2026-07-02 12:00:12 (JST)
New access_token expires_at:             2026-07-02 13:00:11.553141 (JST)
New refresh_token expires_at:            2026-07-02 12:00:13.553145 (JST)

The new refresh_token expires about 1 hour before the new access_token — essentially only ~1 second after the refresh call itself — instead of ~90 days later. We’ve confirmed this pattern across several different shops, not an isolated case.

We reviewed our shopify_app gem integration and confirmed it simply persists whatever refresh_token value comes back in Shopify’s response, with no client-side recalculation of the expiry. Given that, we believe this is likely an issue on Shopify’s side (i.e., the value actually returned by the token endpoint for these refreshes), rather than a bug in our storage logic.

Could someone from the Shopify team please look into this?

That’s concerning - did you log the request IDs from the response?

That would help speed up their investigation so they can review the exact request logs.

Unfortunately, no request ID is available, since the shopify_app and shopify_api gems maintained by Shopify don’t log anything during token refresh.

@masaki_nagaoka are you still seeing this issue? Can you share the actual response (not including the tokens themselves) that you’re seeing?