Skip to content

Commit 36bdc2e

Browse files
committed
Provide example for migrating non expiring offline tokens for expiring ones
1 parent 80a2054 commit 36bdc2e

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

docs/shopify_app/sessions.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,49 @@ end
416416
- When this happens, the user must interact with the app to go through the OAuth flow again to get new tokens
417417
- The refresh process uses database row-level locking to prevent race conditions from concurrent requests
418418

419+
**5. Migrating Existing Shop Installations:**
420+
421+
⚠️ **Important:** When you enable `offline_access_token_expires: true`, only **new shop installations** will automatically receive expiring tokens during the OAuth flow. Existing shop installations with non-expiring tokens will continue using their current tokens until manually migrated.
422+
423+
To migrate existing shops to expiring tokens, use the `ShopifyAPI::Auth::TokenExchange.migrate_to_expiring_token` method. Here's an example background job to migrate all existing shops:
424+
425+
```ruby
426+
# app/jobs/migrate_shops_to_expiring_tokens_job.rb
427+
class MigrateShopsToExpiringTokensJob < ActiveJob::Base
428+
queue_as :default
429+
430+
def perform
431+
# Find shops that haven't been migrated yet (no refresh_token or expires_at)
432+
shops_to_migrate = Shop.where(expires_at: nil, refresh_token: nil, refresh_token_expires_at: nil)
433+
434+
shops_to_migrate.find_each do |shop|
435+
begin
436+
# Migrate to expiring token
437+
new_session = ShopifyAPI::Auth::TokenExchange.migrate_to_expiring_token(
438+
shop: shop.shopify_domain,
439+
non_expiring_offline_token: shop.shopify_token
440+
)
441+
442+
# Store the new session with expiring token and refresh token
443+
Shop.store(new_session)
444+
445+
Rails.logger.info("Successfully migrated #{shop.shopify_domain} to expiring token")
446+
rescue ShopifyAPI::Errors::HttpResponseError => e
447+
# Handle migration errors (e.g., shop uninstalled, network issues)
448+
Rails.logger.error("Failed to migrate #{shop.shopify_domain}: #{e.message}")
449+
rescue => e
450+
Rails.logger.error("Unexpected error migrating #{shop.shopify_domain}: #{e.message}")
451+
end
452+
end
453+
end
454+
end
455+
```
456+
457+
**Migration notes:**
458+
- This is a **one-time, irreversible operation** per shop
459+
- The shop must have the app installed and have a valid access token
460+
- After migration, the shop's offline token will have an expiration date and a refresh token
461+
419462
**Note:** If you choose not to enable expiring offline tokens, the `expires_at`, `refresh_token`, and `refresh_token_expires_at` columns will remain `NULL` and no automatic refresh will occur. Refresh tokens are only available for offline (shop) access tokens. Online (user) access tokens do not support refresh and must be re-authorized through OAuth when expired.
420463

421464
## Migrating from shop-based to user-based token strategy

0 commit comments

Comments
 (0)