Session -> Access Token exchange with managed install query params

Hi there,

I’m experimenting with managed installs, and I noticed there are query params included when the merchant loads our embedded app with managed installs enabled.

I assumed the id_token or session query string parameter was a session token, but the tokens exchange API endpoint is always returning a 400 error (Bad session token).

Is it not possible to actually server side render with a managed install at this time? Meaning, I always have to use the session token retrieval on the frontend through the App Bridge?

I was really hoping I could do the initial session token → access token exchange on the server side before the client side is rendered.

Thanks,

1 Like

This turning into a self answering question.

So it looks like the future of Shopify apps is managed installs.

The difference is that you set your access scopes within the shopify.app.toml and then Shopify will perform the OAuth handshake for you.

When the merchant installs your app, they’re immediately redirected to your app’s home URL (as defined in your app settings).

At this point, the merchant is already authenticated, and the session token information is included in the query string on first load.

Then you can use the Access Token Exchange API to exchange the session token for offline (or online) access tokens.

Alternatively, you can just use the AppBridge on the frontend to retrieve the session token, and then send it to your app’s backend for the exchange.

So, in some ways the Shopify Node API OAuth callback system is an older way of going about it, and it is not compatible with managed installs, because the managed installs flow does not include cookies.

For anyone else (or future me) that forgets about this and tries to use the Shopify Node API package, don’t try to use managed installs with the OAuth features of this package. Instead just perform the token exchange given the session token once the merchant opens your home URL.

1 Like

Hey Dylan!

Thanks for coming back to update on how access scopes and OAuth is managed - do you have any outstanding questions on this that I can help answer?

All good thanks @Liam-Shopify

The managed installs plus token exchange method is working brilliantly. Very happy with it.

The only feedback I have is that this new route doesn’t have as much documentation or tooling as the other way.

There’s no session → access token exchange support built into the officially Shopify Node.js library yet as far as I can see.

And all of the official Node.sj tutorials use the self-managed OAuth callbacks.

But this definitely a huge step in the right direction DX wise.

1 Like

Hi @Dylan , I really appreciate you sharing your experience with managed installation. So far, the documentation around it still feels like a “hidden treasure,” and most app templates seem to rely on the old approach.

Could you share more details about how you handle this in practice, for example, how you handle the first time a merchant enters your app after clicking the Install button? Also, what about middleware on every request to the backend?

Yes, I agree it very much is a hidden treasure. It removes a lot of boilerplate code.

Like I mentioned above, the initial session token is shared via the query string, or alternatively you can just client side render and choose to use the AppBridge’s interface to query it.

Yes, you’ll need to build a middleware that queries your database to make sure the merchant’s record is seeded from the initial install. As far as I’m aware, there’s no way of differentiating between an app install and an app open request.

1 Like

Kind of rubber-ducking here :grinning_face_with_smiling_eyes:
With your posts and some help from AI, I managed to completely kill the old approach using just two new middlewares. The install flow is now super smooth, no session handling, no extra redirects anymore.

Thanks a lot for sharing this. I’m actually thinking about writing a small repo so anyone who comes across this post in the future can benefit from it too.

Hi @Dylan , I just realized that I haven’t handled this situation properly.

When a merchant first loads the app, the access token in my shops table is null (not installed yet or previously uninstalled). In that case, I perform a token exchange request and store the access token.

However, when I update the app scopes in the future, a problem appears. When the merchant opens the app and confirms the new scopes, I don’t have a reliable way to know that I should exchange a new access token, because currently the token exchange only happens when the access token is null.

I initially thought about doing a token exchange on every request, but that’s obviously not a good idea. I also considered using the app scope update webhook, but it feels quite passive, I would still need to set some kind of flag and ask the frontend to trigger a token exchange request.

Have you encountered the same situation? How did you solve it? And even if you didn’t need to handle this case, I’d really appreciate any advice you might have.

Check out the shopify.scopes module in the AppBridge, that’s exactly what it is built for:

I’m assuming you’re adding optional scopes to accounts in the future.

If you’re adding mandatory scopes then Shopify should automatically prompt for re-auth and perhaps you should inspect the scopes list in the response to make sure the local account has the same scopes to determine if a new access token is necessary.

1 Like