blocker bug: OAuth not work if session was lost on SessionStorage!
Also have such error. Looks like for now custom session storage must also have "optional" findSessionsByShopCallback method:
CustomSessionStorage failed to find sessions by shop. Error Details: findSessionsByShopCallback not defined.
but after I added it, it started to search for sessions in another way, so can't find them without update. It starts recursively redirect to /exitiframe, and app not loads and shows "too many redirects" error. When I added exception, not redirect to that path if it's already the same, I received just same error
CookieNotFound [Error]: Cannot complete OAuth process. Could not find an OAuth cookie for shop url: ******.myshopify.com
It's a blocker bug!
Originally posted by @Lancer92 in https://github.com/Shopify/shopify-api-node/issues/486#issuecomment-1250726892
👋🏻 What is the starting point of your app? Are you using the Shopify CLI to generate your app?
If the starting point of your app is the shopify-app-template-node (used by the CLI), and if you're then customizing it to use Custom Session Storage, then the findSessionsByShop method needs to be implemented to support the app template. (It was added to support the app template; it's optional from the API library perspective.)
The app template uses the session storage to track which stores have installed the app (i.e., which shop domains have had at least one completed login session).
Hi Kevin, thanks for the quick answer. Yes, you right, it was shopify cli, after that it was update for the new oauth flow, and ok, it's clear now in which case findSessionsByShop is optional. But is still not clear what to do if session was removed from storage. How to generate new one? trying to
const redirectUrl = await Shopify.Auth.beginAuth(
req,
res,
req.query.shop,
"/api/auth/callback",
app.get("use-online-tokens")
);
results in Error
CookieNotFound [Error]: Cannot complete OAuth process. Could not find an OAuth cookie for shop url:
******.myshopify.com
@Lancer92 what version of the API library is the app using? Maybe the easiest thing to do is share the content of web/package.json, or at least the dependencies/devDependencies sections.
"dependencies": {
"@shopify/shopify-api": "^5.0.1",
"airtable": "^0.11.4",
"compression": "^1.7.4",
"cookie-parser": "^1.4.6",
"cross-env": "^7.0.3",
"express": "^4.18.1",
"serve-static": "^1.15.0"
},
"devDependencies": {
"@serverless/cloud": "^2.10.16",
"jsonwebtoken": "^8.5.1",
"nodemon": "^2.0.15",
"prettier": "^2.7.1",
"pretty-quick": "^3.1.3"
},
@Lancer92 Are you able to provide more details (or, even better, code for a reduced app) that reproduces the error? What platforms/environments are you running this with, what version of Node, browser, etc.?
Do you see a shopify_app_session cookie in your browser when you're attempting to login/authenticate?
I am also using the CustomSessionStorage to implement my session storage. From the example I found on the internet, they don't specifically implement findSessionsByShopCallback. Can you provide an example snippet to implement custom storage? or in order word how can I connect with monogodb?
@jeff0723 To connect wit MongoDB, there's a MongoDBSessionStorage adapter available.
https://github.com/Shopify/shopify-api-node/tree/main/src/auth/session/storage#mongodb
I use it with Serverless Cloud Data. The problem is when sessions can't be found on SessionStorage, the new ones cant be cretead, with already mentined error about cookie. Here is my CustomSessionStorage
import { data } from '@serverless/cloud';
import { Shopify } from "@shopify/shopify-api";
/*
The storeCallback takes in the Session, and sets a stringified version of it on the redis store
This callback is used for BOTH saving new Sessions and updating existing Sessions.
If the session can be stored, return true
Otherwise, return false
*/
async function save(session = {}) {
try {
// Inside our try, we use the `setAsync` method to save our session.
// This method returns a boolean (true if successful, false if not)
return await data.set('sess:' + session.id, JSON.stringify(session), {
label1: session.id.replace('offline_', 'shop:')
});
} catch (err) {
// throw errors, and handle them gracefully in your application
throw new Error(err);
}
}
/*
The loadCallback takes in the id, and uses the getAsync method to access the session data
If a stored session exists, it's parsed and returned
Otherwise, return undefined
*/
async function load(id = 'key') {
try {
let sess = await data.get('sess:' + id);
sess &&= JSON.parse(sess)
// Inside our try, we use `getAsync` to access the method by id
// If we receive data back, we parse and return it
// If not, we return `undefined`
return sess || undefined;
} catch (err) {
throw new Error(err);
}
}
/*
The deleteCallback takes in the id, and uses the `del` method to delete it from the store
If the session can be deleted, return true
Otherwise, return false
*/
async function del(id = 'key') {
try {
// Inside our try, we use the `delAsync` method to delete our session.
// This method returns a boolean (true if successful, false if not)
return await data.remove('sess:' + id);
} catch (err) {
throw new Error(err);
}
}
const delMany = ids => data.remove(ids.map(id => 'sess:' + id))
const findByShop = shop => {
return data.getByLabel('label1', 'shop:' + shop).then(res => {
return res.items.map(({ value }) => JSON.parse(value))
})
}
export const sessionStorage = new Shopify.Session.CustomSessionStorage(
save,
load,
del,
delMany,
findByShop
)
export default sessionStorage;
So for old records there was no indexable "label1" to be able to find all sessions by shop. I fixed It by manually adding them (data migration) But what if there was impossible implement findSessionByShop or if sessions was accidentally cleaned? App is not loading on a store, and only reinstallation helps to solve it, but only developer can investigate it
This issue is stale because it has been open for 90 days with no activity. It will be closed if no further action occurs in 14 days.
We are closing this issue because it has been inactive for a few months. This probably means that it is not reproducible or it has been fixed in a newer version. If it’s an enhancement and hasn’t been taken on since it was submitted, then it seems other issues have taken priority.
If you still encounter this issue with the latest stable version, please reopen using the issue template. You can also contribute directly by submitting a pull request– see the CONTRIBUTING.md file for guidelines
Thank you!