I’m working on a custom Shopify app and having issues with customer authentication redirects. When customers log in through OAuth, they get sent to the store’s order history page instead of my custom redirect URL at localhost:3000/account.
I’m using the customer login endpoint (/account/login) since I need to authenticate customers, not admin users. Here’s my authentication setup:
const initiateCustomerAuth = (req, res) => {
const storeDomain = process.env.SHOP_DOMAIN
const appId = process.env.CLIENT_ID
const permissions = 'read_customers'
const randomState = Math.random().toString(36).substring(2)
req.session.state = randomState
const targetUrl = encodeURIComponent('http://localhost:3000/account')
const callbackUrl = encodeURIComponent(
`http://localhost:8000/api/auth/callback?target_url=${targetUrl}`
)
const loginUrl = `https://${storeDomain}/account/login?client_id=${appId}&scope=${permissions}&redirect_uri=${callbackUrl}&state=${randomState}`
res.redirect(loginUrl)
}
And here’s my callback handler:
const handleAuthCallback = async (req, res) => {
try {
const { code, shop, state, target_url } = req.query
if (!code || !shop || state !== req.session.state) {
return res.status(400).json({ error: 'Authentication failed' })
}
const tokenResponse = await axios.post(
`https://${shop}/admin/oauth/access_token`,
{
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
code,
}
)
const { access_token } = tokenResponse.data
res.cookie('customer_token', access_token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 30 * 24 * 60 * 60 * 1000,
sameSite: 'Strict',
})
res.redirect(target_url || 'http://localhost:3000/account')
} catch (error) {
console.error('OAuth callback error:', error)
res.status(500).json({ error: 'Token exchange failed' })
}
}
The problem is that after successful login, users end up on the store’s orders page instead of my specified redirect URL. Even though I’m setting the redirect_uri parameter correctly, Shopify seems to ignore it completely.
Has anyone encountered this issue before? Any suggestions would be really helpful!