App reviews, troubleshooting, and recommendations
I know there's another question with the same title, but I decided to post mine as I couldn't find the solution there...
The problem is that Shopify.Utils.loadCurrentSession returns undefined, and I can't figure out why.
I have quite a standard setup created following the Node + React tutorial. My relevant code is below. In my view I'm sending a GET request on button click...
// pages/index.tsx
import React from 'react'
import {
Page,
Button,
Layout
} from '@shopify/polaris'
const Index = () => {
const getTheme = () => {
fetch('/api/themes', {
method: 'GET'
})
}
return (
<Page>
<Layout>
<Button onClick={getTheme}>Get theme</Button>
</Layout>
</Page>
)
}
export default Index
...which I intercept in my /api/:path route on the server
// server.js
require('isomorphic-fetch')
require('dotenv').config()
const Koa = require('koa')
const next = require('next')
const Router = require('koa-router')
const {default: Shopify, ApiVersion} = require('@shopify/shopify-api')
const {default: createShopifyAuth, verifyRequest} = require('@shopify/koa-shopify-auth')
Shopify.Context.initialize({
IS_EMBEDDED_APP: true,
API_VERSION: ApiVersion.April21,
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SHOPIFY_API_SCOPES.split(','),
SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
HOST_NAME: process.env.SHOPIFY_APP_URL.replace(/https:\/\//, '')
})
const port = parseInt(process.env.PORT) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({dev})
const handle = app.getRequestHandler()
const ACTIVE_SHOPIFY_SHOPS = {}
app.prepare().then(() => {
// SERVER
const server = new Koa()
server.keys = [Shopify.Context.API_SECRET_KEY]
server.use(
createShopifyAuth({
afterAuth(ctx) {
const {shop, scope, accessToken} = ctx.state.shopify
const {host} = ctx.query
ACTIVE_SHOPIFY_SHOPS[shop] = scope
ctx.redirect(`/?shop=${shop}&host=${host}`)
}
})
)
// ROUTER
const router = new Router()
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
if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
ctx.redirect(`/auth?shop=${shop}`)
} else {
await handleRequest(ctx)
}
})
router.get('/api/:path', async ctx => {
const session = await Shopify.Utils.loadCurrentSession(ctx.req, ctx.res)
const {shop, accessToken} = session
const client = new Shopify.Clients.Rest(shop, accessToken)
const path = ctx.params.path
const themeId = await client.get({path}).then(themes => themes.body.themes.filter(({role}) => role === 'main')[0].id)
})
router.get('(/_next/static/.*)', handleRequest)
router.get('/_next/webpack-hmr', handleRequest)
router.get('(.*)', verifyRequest(), handleRequest)
router.post('/graphql', verifyRequest({returnHeader: true}), async ctx => {
await Shopify.Utils.graphqlProxy(ctx.req, ctx.res)
})
server.use(router.allowedMethods())
server.use(router.routes())
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`)
})
})
I get undefined in this line specifically:
const session = await Shopify.Utils.loadCurrentSession(ctx.req, ctx.res)
I would really appreciate any help, I have been stuck on this the second day now...
Hi,
You have to use authenticated fetch.
import {authenticatedFetch} from '@shopify/app-bridge-utils'
Thanks for the suggestion. I have tried using authenticatedFetch, but for some reason the session is still undefined...
Here's the client-side code where I call fetch:
import {useEffect, useState} from 'react'
import {useAppBridge} from '@shopify/app-bridge-react'
import {authenticatedFetch} from '@shopify/app-bridge-utils'
const Home = () => {
const app = useAppBridge()
const [result, setResult] = useState('')
useEffect(() => {
authenticatedFetch(app)('api/graphql', {
method: 'POST',
body: `{
shop {
primaryDomain {
url
}
}
}`
})
.then(result => result.json())
.then(result => setResult(result))
.catch(error => console.error(error))
}, [])
return (
<>
<h1>HOME</h1>
<p>{result}</p>
</>
)
}
export default Home
And here's the server-side api route:
import Shopify from '@shopify/shopify-api'
import {NextApiRequest, NextApiResponse} from 'next'
export default async function(req: NextApiRequest, res: NextApiResponse) {
const session = await Shopify.Utils.loadCurrentSession(req, res)
console.log(session)
const client = new Shopify.Clients.Graphql(session.shop, session.accessToken)
const body = await client.query(req.body).then(({body}) => body)
res.status(200).json({body})
}
session is still undefined... Which is strange, because if I inspect the req, it does contain an authorization header with `Bearer [token]`
I'm a bit lost as to why I'm not able to access the session...
I have the exact same issue, im using axios with the interceptor to add the Authorization header but still in the backend I cannot get the users sessions:
router.get(
"/api/shops",
verifyRequest({ returnHeader: true }),
async (ctx, next) => {
const session = await Shopify.Utils.loadCurrentSession(
ctx.req,
ctx.res,
true
);
console.log('session', session)
return true;
}
);
Shopify and our financial partners regularly review and update verification requiremen...
By Jacqui Mar 14, 2025Unlock the potential of marketing on your business growth with Shopify Academy's late...
By Shopify Mar 12, 2025Learn how to increase conversion rates in every stage of the customer journey by enroll...
By Shopify Mar 5, 2025