I have looked at the other shopify questions here but this time the error seems to come from something else I believe. I am trying to create/access a shopify app through localhost on nodejs for playing around with the Product API in the future. But encountering the above error:

Here is my NGROK log:

GET  /shopify                  302 Found                                                                                GET  /shopify                  302 Found                                                                                GET  /shopify                  302 Found                                                                                GET  /shopify                  302 Found                                                                                GET  /shopify                  302 Found                                                                                GET  /shopify                  302 Found

1- Here is my index.js file:

///////////// Initial Setup /////////////

const dotenv = require('dotenv').config();
const express = require('express');
const crypto = require('crypto');
const cookie = require('cookie');
const nonce = require('nonce')();
const querystring = require('querystring');
const axios = require('axios');

const shopifyApiPublicKey = process.env.SHOPIFY_API_PUBLIC_KEY;
const shopifyApiSecretKey = process.env.SHOPIFY_API_SECRET_KEY;
const scopes = 'write_products';
const appUrl = 'https://20a11edc124f.ngrok.io/';

const app = express();
const PORT = 3000

app.get('/', (req, res) => {
  res.send('Ello Govna')
});

///////////// Helper Functions /////////////

const buildRedirectUri = () => `${appUrl}/shopify/callback`;

const buildInstallUrl = (shop, state, redirectUri) => `https://${shop}/admin/oauth/authorize?client_id=${shopifyApiPublicKey}&scope=${scopes}&state=${state}&redirect_uri=${redirectUri}`;

const buildAccessTokenRequestUrl = (shop) => `https://${shop}/admin/oauth/access_token`;

const buildShopDataRequestUrl = (shop) => `https://${shop}/admin/shop.json`;

const generateEncryptedHash = (params) => crypto.createHmac('sha256', shopifyApiSecretKey).update(params).digest('hex');

const fetchAccessToken = async (shop, data) => await axios(buildAccessTokenRequestUrl(shop), {
  method: 'POST',
  data
});

const fetchShopData = async (shop, accessToken) => await axios(buildShopDataRequestUrl(shop), {
  method: 'GET',
  headers: {
    'X-Shopify-Access-Token': accessToken
  }
});

///////////// Route Handlers /////////////

app.get('/shopify', (req, res) => {
  const shop = req.query.shop;

  if (!shop) { return res.status(400).send('no shop')}

  const state = nonce();

  const installShopUrl = buildInstallUrl(shop, state, buildRedirectUri())

  res.cookie('state', state) // should be encrypted in production
  res.redirect(installShopUrl);
});

app.get('/shopify/callback', async (req, res) => {
  const { shop, code, state } = req.query;
  const stateCookie = cookie.parse(req.headers.cookie).state;

  if (state !== stateCookie) { return res.status(403).send('Cannot be verified')}

  const { hmac, ...params } = req.query
  const queryParams = querystring.stringify(params)
  const hash = generateEncryptedHash(queryParams)

  if (hash !== hmac) { return res.status(400).send('HMAC validation failed')}

  try {
    const data = {
      client_id: shopifyApiPublicKey,
      client_secret: shopifyApiSecretKey,
      code
    };
    const tokenResponse = await fetchAccessToken(shop, data)

    const { access_token } = tokenResponse.data

    const shopData = await fetchShopData(shop, access_token)
    res.send(shopData.data.shop)

  } catch(err) {
    console.log(err)
    res.status(500).send('something went wrong')
  }
});

///////////// Start the Server /////////////

app.listen(PORT, () => console.log(`listening on port ${PORT}`));

2- Here is my env file

SHOPIFY_API_PUBLIC_KEY=key here
SHOPIFY_API_SECRET_KEY=key here

3- Here is my package.json file

{
  "name": "TestQasim",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^0.20.0",
    "cookie": "^0.4.1",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "nodemon": "^2.0.4",
    "nonce": "^1.0.4"
  }
}

Im using NGROK tunneling and using this link:

https://20a11edc124f.ngrok.io/shopify?shop=testqasim121312.myshopify.com

but getting the above mentioned error.

I have checked the API URLS etc and cannot seem to find any issue in those either.

this is a screenshot of the error

this is a screenshot of the error

5

There are 5 best solutions below

1
David Lazar On

Log into your partner account, and for the App with the API keys, whitelist the url. It really is that simple.

0
Ravi Thummar On

check you ngrok url with you app setup url and Allowed redirection URL(s) both solub be same like https or http check properly

0
rrallvv .J On

For someone who has the same problem later, I leave a message. I just solved it.

In your package.json, you might have this command. => "dev": "node server.js"

It never restart your server when code is edited. So, after chaing ngrok address(ex, https://12k1ml2kd1m.ngrok.io), restart your server.

In short, change your ngrok address and restart your node server.

2
greazzy On

Incase you're still facing this issue,

Remove the trailing slash from the appURL, I think that should fix this issue.

Use const appUrl = 'https://20a11edc124f.ngrok.io'

not const appUrl = 'https://20a11edc124f.ngrok.io/'

and don't forget to restart your node server.

0
qskane On

In my case, Shopify automatically generates the .env file and automatically adds the redirect URL whitelist, but the problem is that Shopify auto-populates the wrong values.

The autofill value is https://36f6-45-251-107-111.ngrok.io/auth/callback

The correct value is: https://36f6-45-251-107-111.ngrok.io/shopify/auth/callback

So please check if the redirect URL is consistent with the whitelist after decoding the URL in the error page.