Shopify / shopify-app-template-node

MIT License
869 stars 391 forks source link

Using online and offline tokens at the same time with the express boiler. #1170

Closed Michael-Gibbons closed 1 year ago

Michael-Gibbons commented 1 year ago

Issue summary

For most apps, online and offline tokens are needed. Online tokens for safe, time expired, user scoped, requests from the frontend. And offline tokens for long term actions like cron jobs and webhooks.

Currently this boiler uses an app level express variable use-online-tokens to determine which to use, which is less than ideal.

The solution to this is relatively simple, use the loadOfflineSession method in @shopify/shopify-api/dist/utils/load-offline-session.js, check for the existence of an offline session, if it does not exist then create it.

Then remove all references to the use-online-tokens variable.

This has the effect of always storing 1 offline session for each shop alongside all the online sessions for all shops.

I will open a PR for this, even if it doesn't end up being merged I hope it will help some of you implement this.

The only (very minor) downside to this implementation is there will be 2 OAuth redirects on the first app load. 1 for the online token, 1 for the offline token. This is unavoidable without shopify adding OAuth support to retrieve an offline token and an online token in 1 request. After the offline token is stored in the database there will only be one OAuth redirect.

Michael-Gibbons commented 1 year ago

@paulomarg @mkevinosullivan

Michael-Gibbons commented 1 year ago

End usage would be like this


import loadOfflineSession from "@shopify/shopify-api/dist/utils/load-offline-session.js";

function myFunctionThatNeedsAnOfflineToken(req, res, next){
  const offlineSession = await loadOfflineSession.default(req.query.shop) // if not using middleware get shop url from req object
  const accessToken = offlineSession.accessToken
  // do cool things with access token
}
mkevinosullivan commented 1 year ago

HI @Michael-Gibbons,

In the latest version of the template which uses @shopify/shopify-app-express, there's a configuration parameter called useOnlineTokens. If set to false, the shopify-app-express package will obtain the offline token during OAuth and continue on.

However, if set to true, the shopify-app-express package will get the offline token, save it, then restart the OAuth process again and get an online token.

When it comes to retrieving the session, the following call...

const sessionId = await shopify.api.session.getCurrentId({
  isOnline: X,
  rawRequest: req,
  rawResponse: res,
});

... will return the offline session id when X is false or the online session id when X is true, which can then be used to obtain the actual session from storage.

Note that shopify in this case in an instantiation of shopifyApp from the @shopify/shopify-app-express package.