Guides

Developer guide

Shopify OAuth and managed install in Rails apps

A guide to the current Shopify installation model for Rails apps, explaining where managed install replaces older OAuth assumptions and where authorization code grant still matters.

Updated March 12, 2026
15 min read
Editorial note: A lot of Rails Shopify codebases still say “OAuth” when they actually mean four different things: install, session auth, Admin API access, and legacy redirect glue that should no longer define the app architecture.

What changed in Shopify app installation

Older Shopify app tutorials trained developers to think of installation as a redirect ceremony owned by the app. Merchant clicks install, app starts OAuth, app receives a callback, app exchanges a code, and app stores a token.

That is no longer the best default for embedded apps. Shopify’s current managed install model changes the center of gravity. Shopify documents managed installation as an installation method where Shopify installs the app and updates access scopes without making any calls to the app. That is a real shift, not a marketing synonym.

“without making any calls to the app”

This matters because it kills a bunch of old assumptions:

  • installation is no longer primarily your redirect flow
  • scope declaration moves into app configuration
  • scope updates are handled by Shopify-managed prompts
  • embedded app auth should stop pretending install-time OAuth is the whole story

Shopify’s auth overview now says the starter app follows best practices by installing on stores using Shopify managed installation and authorizing embedded apps using session tokens and token exchange. In other words, the platform is not being subtle here. It is trying to drag you away from your 2022 callback controller.

“Installing on stores using Shopify managed installation.”

In Rails terms, installation gets simpler and your server becomes less responsible for browser choreography and more responsible for durable app behavior after installation. That is a good trade. Your app server should be busy doing useful work, not performing interpretive dance with redirect URIs.

How a modern Rails embedded app should think about auth

The clean mental model for a modern embedded Rails app is:

  • Shopify-managed install for installation and required scope changes
  • session tokens for authenticating embedded frontend requests into Rails
  • token exchange for acquiring Admin API access tokens
  • online or offline token usage based on the backend job being performed

Shopify’s managed install guide is explicit that embedded apps using Shopify managed install should acquire access tokens through token exchange. Shopify’s embedded auth tutorial says the flow consists of configuring access scopes through the CLI, then retrieving and validating session tokens, then exchanging those tokens for API access tokens, then handling post-authorization tasks.

“Embedded apps using Shopify managed install should acquire access tokens through token exchange.”

That is a much better model than saying, “we do OAuth”, because “OAuth” is often used to mean install flow, session verification, Admin API authorization, and whatever strange callback code survived the last rewrite.

Stop overloading the word OAuth

In a modern embedded Rails app, installation, session authentication, and Admin API authorization are related, but they are not the same thing. Treating them as one blob is how good apps grow very dumb auth code.

The default configuration shape should be declarative:

[access_scopes]
scopes = "read_products,write_products"
optional_scopes = ["read_orders"]
 
# Omit this or leave it false to use Shopify managed install
# use_legacy_install_flow = true

Shopify’s app configuration docs say that when use_legacy_install_flow is omitted or false, scopes are saved in the app configuration and automatically requested when the app is installed or when the declared scopes change. That is the managed-install path.

“When omitted or false

In Rails, that means your app code should focus less on “how do I redirect to install” and more on “what happens after the app is installed and authenticated”. That shift is where cleaner architectures come from.

Where authorization code grant still belongs

Authorization code grant is not dead. It is just no longer the default center of the universe for embedded apps.

Shopify’s current authorization code grant guide could not be much clearer. It says embedded apps should use token exchange to acquire access tokens, all apps should use Shopify managed installation, and the guide is only relevant to non-embedded apps and legacy apps that are not using Shopify managed installation.

“This guide is only relevant to non-embedded apps and legacy apps”

ScenarioRecommended install/auth shapeWhyMain caution
New embedded Rails appManaged install + session tokens + token exchangeMatches Shopify’s current recommended modelDo not rebuild legacy redirect logic out of habit
Non-embedded appAuthorization code grantThe embedded token-exchange model does not apply the same wayKeep install and session assumptions separate
Legacy embedded app with older install flowAuthorization code grant until migratedSometimes you must maintain existing behavior before replacing itDo not mistake “still running” for “still the right default”

This distinction matters because teams still copy old OAuth tutorials into new embedded apps and then wonder why the app keeps flickering through redirects like it is haunted by 2023.

Shopify’s 2024 changelog entry introducing managed install and OAuth2 token exchange spelled out the point very directly: the new flows eliminate unnecessary redirects and screen flicker during embedded app load and install.

“eliminate screen flickering due to full page redirects”

Migrating old Rails assumptions

Migrating an older Rails app to the modern model usually means deleting install-time assumptions, not adding more auth framework poetry.

The most common old assumptions that need to go are:

  • assuming install always calls your callback endpoint
  • treating the app server as the source of truth for required scopes
  • using install redirects as the place where every shop record is initialized
  • mixing embedded session auth with older cookie-based assumptions
  • treating access-scope changes as a custom app-controlled flow

In the managed-install model, scope changes are declarative. Shopify’s access-scope management docs say you update the scopes or optional_scopes in TOML and deploy. When scopes increase, merchants are prompted when they open the app. When scopes decrease, the app loses access automatically when the merchant opens the app. The app/scopes_update webhook is triggered in both cases.

“Merchants will be prompted to approve the updated access scopes when they open your app.”

That means the migration checklist in Rails is usually something like this:

# old assumptions to remove
#
# 1. install callback as the mandatory shop bootstrap path
# 2. dynamic required-scope logic scattered through controllers
# 3. cookie-based embedded auth fallback behavior
# 4. code paths that assume "OAuth redirect happened" means "shop is ready"
#
# new assumptions to adopt
#
# 1. required scopes live in app config
# 2. embedded requests authenticate with session tokens
# 3. Admin API access comes from token exchange
# 4. shop initialization is safe to perform on first verified backend contact
# 5. scope changes are handled through managed install behavior and webhook awareness

You should also make the legacy path explicit if you still need it:

[access_scopes]
scopes = "read_products,write_products"
use_legacy_install_flow = true

That is not the recommended direction for a new embedded app. It is the “we are maintaining older behavior while we migrate” direction. Those are not the same thing, and confusing them is how temporary code becomes permanent folklore.

One more migration lesson that matters in Rails: do not let “OAuth callback success” remain the place where your entire app lifecycle happens. Webhook registration, shop persistence, feature defaults, and offline token storage should all survive a world where install redirects are no longer the star of the show.

If you are rebuilding the app shell at the same time, pair this guide with

React frontend plus Rails backend for Shopify embedded apps

. If you are cleaning up the request-auth side, pair it with

Shopify session tokens in Rails

.

The migration smell test

If removing your install callback would break half the app, your codebase is not “OAuth-based”. It is install-callback-dependent, which is a much less flattering diagnosis.

Best internal links

Sources and further reading

FAQ

Should a new embedded Rails app start with authorization code grant?

No. Shopify recommends managed install and token exchange for embedded apps. Authorization code grant is mainly for non-embedded apps and legacy cases.

Does managed install mean my Rails app no longer handles installation redirects?

Yes, that is the point. Shopify installs the app and updates access scopes without calling your app during installation or scope changes.

Where do required scopes live with managed install?

In your app configuration, typically the TOML file you deploy with Shopify CLI. That configuration becomes the source of truth for install-time scopes.

Can I still use legacy install flow in Rails if I have to?

Yes, but it should be an explicit legacy choice. Shopify’s app configuration supports `use_legacy_install_flow`, and the authorization code grant docs are now positioned for non-embedded and legacy apps.

Related resources

Keep exploring the playbook

Guides

Shopify session tokens in Rails

A Rails-focused guide to Shopify session tokens for embedded apps, covering the Shopify App gem, token exchange, frontend request flow, and the mistakes that still break production auth.

guidesShopify developersession tokens