Hi,
I need offline access token for some background work. So we are using offline access token. In older node code we are directly using accessMode: offline.
But as per latest code using app-bridge, by default access mode is offline so we are not providing offline mode explicitly.
It was working fine before (Or even before upgrading @Shopify_77 /app-bridge-react from 1.29.0 to 2.0.3
from "@shopify/app-bridge-react": "2.0.3",
When app installed, we store access token in our background process, but after some time (may be 1 day) we are getting 401 error in background process.
Then we need launch app again and we get new access token (Which is not good idea for us to ask client to re launch app).
Is anyone facing such issue ? PFB code snipet
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: [
"read_products",
"write_products"
], //process.env.SCOPES.split(","),
HOST_NAME: process.env.HOST.replace(/https:\/\//, ""),
API_VERSION: ApiVersion.October20,
IS_EMBEDDED_APP: true,
// This should be replaced with your preferred storage strategy
//SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
// PROD : Redis Pass the sessionStorage methods to pass into a new instance of `CustomSessionStorage`
SESSION_STORAGE: new Shopify.Session.CustomSessionStorage(
sessionStorage.storeCallback,
sessionStorage.loadCallback,
sessionStorage.deleteCallback
),
});
// Storing the currently active shops in memory will force them to re-login when your server restarts. You should
// persist this object in your app.
const ACTIVE_SHOPIFY_SHOPS = {};
app.prepare().then(async () => {
const server = new Koa();
const router = new Router();
server.keys = [Shopify.Context.API_SECRET_KEY];
server.use(
createShopifyAuth({
async afterAuth(ctx) {
// Access token and shop available in ctx.state.shopify
const { shop, accessToken, scope } = ctx.state.shopify;
const host = ctx.query.host;
1 Like
Same issue here… Offline mode is default, but our token expires after one day. We are hosting on heroku.
Did you find a solution?
This article here https://community.shopify.com/c/shopify-apis-and-sdks/will-access-token-expired/td-p/559870
does not help, because we use offline mode.
In our code, which stems from the shopify app example there is a line
// Storing the currently active shops in memory will force them to re-login when your server restarts. You should
// persist this object in your app.
const ACTIVE_SHOPIFY_SHOPS = {};
This is currently not persisted in our app. Perhaps this could help?
@hugo4711
ok, I have workaround for this.
First thing, default access mode is Online (if not mention in server.js) not a offline (Seems some issue in documentation)
If you are using embedded app, then your frontend (my case react) must need online token for process as per new version.
But for me, I also need offline token to store in my backend database for background work which will be done by my NodeJS server.
So here I need 2 token,
- Online, for frontend Use (React).
- Offline, for background use (NodeJS)
Now I generate online token when app launch and checking in background if I have offline token or not. If offline token is missed then I regenerate auth flow (with prefix /install) and generate offline token and send it to my backend server to store.
So I have 2 auth flow in my code as below :
server.use(
createShopifyAuth({
async afterAuth(ctx) {
// Access token and shop available in ctx.state.shopify
const { shop, accessToken, scope } = ctx.state.shopify;
const host = ctx.query.host;
ACTIVE_SHOPIFY_SHOPS[shop] = scope;
console.log("Porcessing Online token for frontend use...");
// Redirect to app with shop parameter upon auth
ctx.redirect(`/?shop=${shop}&host=${host}`);
},
})
);
server.use(
createShopifyAuth({
accessMode: "offline",
prefix: "/install", // you need to add additional redirect URL /install/auth/callback in partner app Allowed redirection URL(s)
async afterAuth(ctx) {
// Access token and shop available in ctx.state.shopify
const { shop, accessToken, scope } = ctx.state.shopify;
console.log("Genrated offline token, saving in background DB");
ctx.redirect(`/?shop=${shop}`);
},
})
);
router.get("/", async (ctx) => {
const shop = ctx.query.shop;
// This shop hasn't been seen yet, go through OAuth to create a session
// check in background where you have offline token saved or not and based on condition call offline auth
if (condition) {
ctx.redirect(`/install/auth?shop=${shop}`); // it will call offline auth
} else if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
return ctx.redirect(`/auth?shop=${shop}`);
} else {
await handleRequest(ctx);
}
});
So basically we have both access mode in my app.
Hope it will help.
Thanks,
1 Like
I believe there is an easier way, if you go off the default Shopify Node App, just setting the variable USE_ONLINE_TOKENS = false in index.js will stop the tokens from changing. You can then fetch the token using a call such as this:
async function getShopUrlFromSession (req, res) {
const session = await Shopify.Utils.loadCurrentSession(req, res, false);
return session;
};
Session will be an object that will have a property accessToken which is your offline access token.