Shopify / koa-shopify-auth

DEPRECATED Middleware to authenticate a Koa application with Shopify
MIT License
80 stars 63 forks source link

loadCallback of CustomSessionStorage has id as "offline_undefined" #82

Closed avocadoslab closed 3 years ago

avocadoslab commented 3 years ago

Issue summary

Using accessMode: offline, seeing issue where loadCallback has id as offline_undefined instead of offline_shop-name.myshopify.com.

This happens when I call app API's from Shopify storefront through script tag.

Expected behavior

id coming in loadCallback shouldn't be offline_undefined

Actual behavior

Error: CustomSessionStorage failed to load a session. Error Details: TypeError: Cannot read property 'id' of null
       at SessionStorageError.ShopifyError [as constructor] (/Users/green/shopify/jwt-app/node_modules/@shopify/shopify-api/dist/error.js:13:28)
       at new SessionStorageError (/Users/green/shopify/jwt-app/node_modules/@shopify/shopify-api/dist/error.js:172:42)
       at CustomSessionStorage.<anonymous> (/Users/green/shopify/jwt-app/node_modules/@shopify/shopify-api/dist/auth/session/storage/custom.js:46:31)
       at step (/Users/green/shopify/jwt-app/node_modules/@shopify/shopify-api/node_modules/tslib/tslib.js:143:27)
       at Object.throw (/Users/green/shopify/jwt-app/node_modules/@shopify/shopify-api/node_modules/tslib/tslib.js:124:57)
       at rejected (/Users/green/shopify/jwt-app/node_modules/@shopify/shopify-api/node_modules/tslib/tslib.js:115:69)
       at processTicksAndRejections (internal/process/task_queues.js:97:5)

Code

server.js
``` import "@babel/polyfill"; import dotenv from "dotenv"; import "isomorphic-fetch"; import createShopifyAuth, { verifyRequest } from "@shopify/koa-shopify-auth"; import Shopify, { ApiVersion } from "@shopify/shopify-api"; import Koa from "koa"; import next from "next"; import Router from "koa-router"; import { MongoClient } from "mongodb"; dotenv.config(); const port = parseInt(process.env.PORT, 10) || 8081; const dev = process.env.NODE_ENV !== "production"; const app = next({ dev, }); const handle = app.getRequestHandler(); async function storeCallback(session) { // Store session in DB. return true; } async function loadCallback(id) { // Incoming id coming as offline_undefined // Load session from DB return session; } async function deleteCallback(id) { // Delete from DB. } Shopify.Context.initialize({ API_KEY: process.env.SHOPIFY_API_KEY, API_SECRET_KEY: process.env.SHOPIFY_API_SECRET, SCOPES: process.env.SCOPES.split(","), HOST_NAME: process.env.HOST.replace(/https:\/\//, ""), API_VERSION: ApiVersion.October20, IS_EMBEDDED_APP: true, SESSION_STORAGE: new Shopify.Session.CustomSessionStorage( storeCallback, loadCallback, deleteCallback ) }); const ACTIVE_SHOPIFY_SHOPS = {}; MongoClient.connect(MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true, }).then(async connection => { console.info(`Successfully connected to Mongo`); const mongodb = connection; app.prepare().then(async () => { const server = new Koa(); const router = new Router(); server.keys = [Shopify.Context.API_SECRET_KEY]; server.use( createShopifyAuth({ apiKey: SHOPIFY_API_KEY, secret: SHOPIFY_API_SECRET, scopes: [SCOPES], accessMode: "offline", async afterAuth(ctx) { // Access token and shop available in ctx.state.shopify const { shop, accessToken, scope } = ctx.state.shopify; ACTIVE_SHOPIFY_SHOPS[shop] = scope; if (!response.success) { console.log( `Failed to register APP_UNINSTALLED webhook: ${response.result}` ); } // Redirect to app with shop parameter upon auth ctx.redirect(`/?shop=${shop}`); }, }) ); const handleRequest = async (ctx) => { await handle(ctx.req, ctx.res); ctx.respond = false; ctx.res.statusCode = 200; }; router.get("/", async (ctx) => { const shop = ctx.query.shop; // This shop hasn't been seen yet, go through OAuth to create a session if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) { ctx.redirect(`/auth?shop=${shop}`); } else { await handleRequest(ctx); } }); server.use(require("./api")); router.get("(/_next/static/.*)", handleRequest); // Static content is clear router.get("/_next/webpack-hmr", handleRequest); // Webpack content is clear router.get("(.*)", verifyRequest({ accessMode: "offline" }), handleRequest); // Everything else must have sessions server.use(router.allowedMethods()); server.use(router.routes()); server.listen(port, () => { console.log(`> Ready on http://localhost:${port}`); }); }); }); ```
avocadoslab commented 3 years ago

Closing as this was a bug in my custom middleware.

luciilucii commented 3 years ago

Hey @pratiknikam do you remember what caused this bug? Struggling with something similar right now

rodrigograca31 commented 2 years ago

Same here

galmis commented 2 years ago

Same here