skip to Main Content

enter image description hereI’m developing an app for Shopify. Currently under development stage. Until now, I have successfully managed to authorise the app and then redirect it back to admin page using the Embedded App SDK. However, when I return to the admin page, it gives me an error saying Request origin cannot be verified.

The console shows Failed to load resource: the server responded with a status of 403 (Forbidden)
The URL in the console is something like this https://myshop.myshopify.com/admin/apps/dfdjf4343343434343434bfdf/shopify/shopify/callback?code=ffdfdffd&hmac=fdfdfdfdfdfdfdfdfddfdfdfdfdf&shop=myshop.myshopify.com&state=151193864548800&timestamp=1511938648

The fdfdfdfdfdfdfdfdfddfdfdfdfdf are just random characters that I’ve replaced instead of a hash. FYI – I’ve removed the app name and user profile name and avatar from the image.

3

Answers


  1. This is happening because, you are unable to match state, that is set in cookie, while responding with redirect url

    const ShopifyToken = require('shopify-token')
    
    const forwardingAddress = process.env.HOST
    
    const shopifyToken = new ShopifyToken({
      sharedSecret: process.env.SHOPIFY_API_SECRET,
      redirectUri: forwardingAddress + '/shopify/callback',
      apiKey: process.env.SHOPIFY_API_KEY
    })
    
    
    const shopify = {
      // use this for authentication
      auth: (req, res, next) => {
        const shop = req.query.shop
        if (!shop) {
          return res.status(400).send('Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request')
        }
        const shopRegex = /^([w-]+).myshopify.com/i
        const shopName = shopRegex.exec(shop)[1]
        const state = shopifyToken.generateNonce()
        const url = shopifyToken.generateAuthUrl(shopName, scopes, state)
        res.cookie('state', state)
        res.redirect(url)
      },
    
      // use this as your callback function
      authCallback: async (req, res) => {
        const { shop, hmac, code, state } = req.query
        const stateCookie = cookie.parse(req.headers.cookie).state
        if (state !== stateCookie) {
        // you are unable to set proper state ("nonce") in this case, thus you are getting this error
          return res.status(403).send('Request origin cannot be verified')
        }
        if (!shop || !hmac || !code) {
          res.status(400).send('Required parameters missing')
        }
        let hmacVerified = shopifyToken.verifyHmac(req.query)
        console.log(`verifying -> ${hmacVerified}`)
        // DONE: Validate request is from Shopify
        if (!hmacVerified) {
          return res.status(400).send('HMAC validation failed')
        }
        const accessToken = await shopifyToken.getAccessToken(shop, code)
        const shopRequestUrl = 'https://' + shop + '/admin/shop.json'
        const shopRequestHeaders = {
          'X-Shopify-Access-Token': accessToken
        }
        try {
          const shopResponse = await request.get(shopRequestUrl, { headers: shopRequestHeaders })
          res.status(200).end(shopResponse)
        } catch (error) {
          res.status(error.statusCode).send(error.error.error_description)
        }
      }
    }
    Login or Signup to reply.
  2. const express = require('express');
    const router = express.Router();
    const dotenv = require('dotenv').config();
    const cookie = require('cookie');
    const requestPromise = require('request-promise');
    const ShopifyToken = require('shopify-token');
    
    const scopes = "write_products";
    const forwardingAddress = process.env.HOST;
    
    var shopifyToken = new ShopifyToken({
    sharedSecret: process.env.SHOPIFY_API_SECRET,
    redirectUri: forwardingAddress + '/shopify/callback',
    apiKey: process.env.SHOPIFY_API_KEY
    })
    
    router.get('/shopify', (req, res) => {
    const shop = req.query.shop;
    if (!shop) {
        return res.status(400).send('Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request')
    }
    const shopRegex = /^([w-]+).myshopify.com/i
    const shopName = shopRegex.exec(shop)[1]
    const state = shopifyToken.generateNonce();
    const url = shopifyToken.generateAuthUrl(shopName, scopes, state);
    res.cookie('state', state);
    res.redirect(url);
    });
    
    router.get('/shopify/callback', (req, res) => {
    const { shop, hmac, code, state } = req.query;
    const stateCookie = cookie.parse(req.headers.cookie).state;
    
    if (state !== stateCookie) {
        // you are unable to set proper state ("nonce") in this case, thus you are getting this error
        return res.status(403).send('Request origin cannot be verified')
    }
    if (!shop || !hmac || !code) {
        res.status(400).send('Required parameters missing')
    }
    let hmacVerified = shopifyToken.verifyHmac(req.query)
    console.log(`verifying -> ${hmacVerified}`)
    
    // DONE: Validate request is from Shopify
    if (!hmacVerified) {
        return res.status(400).send('HMAC validation failed')
    }
    const accessToken = shopifyToken.getAccessToken(shop, code);
    const shopRequestUrl = 'https://' + shop + '/admin/products.json'
    const shopRequestHeaders = {
        'X-Shopify-Access-Token': accessToken
    }
    try {
        const shopResponse = requestPromise.get(shopRequestUrl, { headers: shopRequestHeaders })
        res.status(200).send(shopResponse)
    } catch (error) {
        res.status(error.statusCode).send(error.error.error_description)
    }
    
    });
    
    module.exports = router;
    Login or Signup to reply.
  3. Simple as this is, also make sure that the protocol matches from what you typed in to start the app install.

    If you accidentally use http for http://you.ngrok.io/ but your callback redirects to https (i.e. https://you.ngrok.io/auth/callback), the OAuth handshake will fail.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search