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;
}
);
Are you ready to take your business to the next level? Look no further than the latest ...
By SarahF_Shopify Apr 15, 2024We’re keeping the ball rolling to make sure you’re always ahead of the game. So buckle ...
By JasonH Apr 8, 2024Portrait of Stephen positioned next to an image of planet Earth, with the Stephen's World ...
By JasonH Mar 18, 2024