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.
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 = trueShopify’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.
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 awarenessYou should also make the legacy path explicit if you still need it:
[access_scopes]
scopes = "read_products,write_products"
use_legacy_install_flow = trueThat 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
Shopify session tokens in Rails
for the embedded request-auth side after installation.
React frontend plus Rails backend for Shopify embedded apps
for the broader production architecture that managed install fits into.
Shopify Admin GraphQL patterns in Rails
for keeping Admin API work where it belongs after token acquisition.
Sources and further reading
Shopify Dev: Enable Shopify-managed installations for your app
Shopify Dev: Authentication and authorization
Shopify Dev: Implement authorization code grant manually
Shopify Dev: Exchange a session token for an access token
Shopify Dev: Manage access scopes
Shopify Dev: App configuration
Shopify shopify_app README
Shopify shopify_app authentication docs
Shopify Dev Changelog: OAuth2 token exchange and Shopify managed install
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
React frontend plus Rails backend for Shopify embedded apps
How to structure a Shopify embedded app with React on the frontend and Rails on the backend, including auth boundaries, deployment shape, and the operational tradeoffs that matter in production.
Shopify app proxy guide for Rails backends and React frontends
A practical guide to using Shopify app proxies with a Rails backend and React frontend, including request validation, frontend architecture, and the cases where proxies are the wrong tool.
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.