Shopify/shopify-app-template-node

How to validate webhooks!!

sujalmakkar opened this issue · 10 comments

I submitted my app for review. They rejected it saying that the shop/redact webhook should return status 401 if the request isn't made from Shopify.

Please guide me through it.

app.post('/webhooks/shop/redact',async (req,res)=>{
res.status(200).send({message:'Updated'})
})

You need to verify the Hmac hash to confirm that it's from Shopify. You can add this function as Express middleware:

validateWebhookRequest.js

  import { Shopify, ShopifyHeader } from "@shopify/shopify-api";
  import crypto from "crypto";
  
  export default function validateWebhookRequest(req, res, next) {
	  try {
		  const generatedHash = crypto
			  .createHmac("SHA256", Shopify.Context.API_SECRET_KEY)
			  .update(JSON.stringify(req.body), "utf8")
			  .digest("base64");
		  const hmac = req.get(ShopifyHeader.Hmac); // Equal to 'X-Shopify-Hmac-Sha256' at time of coding
  
		  const safeCompareResult = Shopify.Utils.safeCompare(generatedHash, hmac);
  
		  if (!safeCompareResult) {
			  res.status(200);
			  next();
		  } else {
			  return res.status(401).json({ succeeded: false, message: "Not Authorized" }).send();
		  }
	  } catch (error) {
		  console.log(error);
		  return res.status(401).json({ succeeded: false, message: "Error caught" }).send();
	  }
  }

server.js

...
app.post("/api/webhooks", validateWebhookRequest, Shopify.Webhooks.Registry.process);
...

Can someone fro Shopify confirm either of these work?

I'm confused why the template would have broken implementation.

Update: https://github.com/Shopify/shopify-api-js/blob/3de67ce34d9a85707d00462d9414c2f38fce4f07/docs/reference/utils/validateHmac.md

This seems to be an invalid approach since this method looks for query params and not header, as specified in the webhook specs.

The middleware suggested further up also breaks over changes to shopify API.

I've finally landed on something that works with this middleware:

import crypto from "crypto";
// get SHOPIFY_API_SECRET from env variables
const SHOPIFY_API_SECRET = process.env.SHOPIFY_API_SECRET;



export default async function validateWebhookRequest(req, res, next) {
    try {
        // get raw body data
        const rawBody = req.rawBody;

        // get HMAC header from request
        const hmacHeader = req.get('X-Shopify-Hmac-SHA256');
        // create hmac object
        const hmac = crypto.createHmac('sha256', SHOPIFY_API_SECRET);

        // create hmac hash from raw body
        const hash = hmac.update(rawBody, 'utf8').digest('base64');

        // compare our hash with Shopify's hash
        if (hash === hmacHeader) {
            console.log('hmac success');
            res.status(200);
            next();
        } else {
            console.log('hmac failed');
            return res.status(401).json({succeeded: false, message: "Not Authorized"}).send();
        }
    } catch (error) {
        console.log('error in hmac validation');
        console.log(error);
        return res.status(401).json({succeeded: false, message: "Error caught"}).send();
    }
}

Thanks to GPT 4 for helping me out of this mess.

app.post('/webhooks/shop/redact',async (req,res)=>{
res.status(200).send({message:'Updated'})
})

Hi Sir/Maam I am new to Shopify App Development, I had devloped my app, and add all the required Webhooks.
But when I submit the App on Shopify Partner Dashboad --> All Apps --> AppName --> Distribution -->
Shopify App Store listing
Attention Draft
Help merchants discover your app and how it can help them build their businesses.
When you’re ready, submit the app for review. Review wait times vary, but we’ll email you about your submission.

                                           **Manage Submission** 

After Clicking "Manage Submission" I filled the little requirements and then I am stuck in

             **Run an automated check for common errors**

Check is in progress. You can leave this page while it's running, if it takes more than a few minutes.

Configured mandatory compliancewebhooks. (Ok working)
Implement an HMAC Signature to verify webhooks. (X Not working)
Used a Valid TLS certificate. (Ok working)

I am stuck in Implement an HMAC Signature to verify webhooks. (X Not working), please someone guide me, it will be more thankful.

You need to verify the Hmac hash to confirm that it's from Shopify. You can add this function as Express middleware:

validateWebhookRequest.js

  import { Shopify, ShopifyHeader } from "@shopify/shopify-api";
  import crypto from "crypto";
  
  export default function validateWebhookRequest(req, res, next) {
	  try {
		  const generatedHash = crypto
			  .createHmac("SHA256", Shopify.Context.API_SECRET_KEY)
			  .update(JSON.stringify(req.body), "utf8")
			  .digest("base64");
		  const hmac = req.get(ShopifyHeader.Hmac); // Equal to 'X-Shopify-Hmac-Sha256' at time of coding
  
		  const safeCompareResult = Shopify.Utils.safeCompare(generatedHash, hmac);
  
		  if (!safeCompareResult) {
			  res.status(200);
			  next();
		  } else {
			  return res.status(401).json({ succeeded: false, message: "Not Authorized" }).send();
		  }
	  } catch (error) {
		  console.log(error);
		  return res.status(401).json({ succeeded: false, message: "Error caught" }).send();
	  }
  }

server.js

...
app.post("/api/webhooks", validateWebhookRequest, Shopify.Webhooks.Registry.process);
...

app.post('/webhooks/shop/redact',async (req,res)=>{
res.status(200).send({message:'Updated'})
})

Hi Sir/Maam I am new to Shopify App Development, I had devloped my app, and add all the required Webhooks.
But when I submit the App on Shopify Partner Dashboad --> All Apps --> AppName --> Distribution -->
Shopify App Store listing
Attention Draft
Help merchants discover your app and how it can help them build their businesses.
When you’re ready, submit the app for review. Review wait times vary, but we’ll email you about your submission.

                                           **Manage Submission** 

After Clicking "Manage Submission" I filled the little requirements and then I am stuck in

             **Run an automated check for common errors**

Check is in progress. You can leave this page while it's running, if it takes more than a few minutes.

Configured mandatory compliancewebhooks. (Ok working)
Implement an HMAC Signature to verify webhooks. (X Not working)
Used a Valid TLS certificate. (Ok working)

I am stuck in Implement an HMAC Signature to verify webhooks. (X Not working), please someone guide me, it will be more thankful.

Can someone fro Shopify confirm either of these work?

I'm confused why the template would have broken implementation.

Update: https://github.com/Shopify/shopify-api-js/blob/3de67ce34d9a85707d00462d9414c2f38fce4f07/docs/reference/utils/validateHmac.md

This seems to be an invalid approach since this method looks for query params and not header, as specified in the webhook specs.

The middleware suggested further up also breaks over changes to shopify API.

I've finally landed on something that works with this middleware:

import crypto from "crypto";
// get SHOPIFY_API_SECRET from env variables
const SHOPIFY_API_SECRET = process.env.SHOPIFY_API_SECRET;



export default async function validateWebhookRequest(req, res, next) {
    try {
        // get raw body data
        const rawBody = req.rawBody;

        // get HMAC header from request
        const hmacHeader = req.get('X-Shopify-Hmac-SHA256');
        // create hmac object
        const hmac = crypto.createHmac('sha256', SHOPIFY_API_SECRET);

        // create hmac hash from raw body
        const hash = hmac.update(rawBody, 'utf8').digest('base64');

        // compare our hash with Shopify's hash
        if (hash === hmacHeader) {
            console.log('hmac success');
            res.status(200);
            next();
        } else {
            console.log('hmac failed');
            return res.status(401).json({succeeded: false, message: "Not Authorized"}).send();
        }
    } catch (error) {
        console.log('error in hmac validation');
        console.log(error);
        return res.status(401).json({succeeded: false, message: "Error caught"}).send();
    }
}

Thanks to GPT 4 for helping me out of this mess.

app.post('/webhooks/shop/redact',async (req,res)=>{
res.status(200).send({message:'Updated'})
})

Hi Sir/Maam I am new to Shopify App Development, I had devloped my app, and add all the required Webhooks.
But when I submit the App on Shopify Partner Dashboad --> All Apps --> AppName --> Distribution -->
Shopify App Store listing
Attention Draft
Help merchants discover your app and how it can help them build their businesses.
When you’re ready, submit the app for review. Review wait times vary, but we’ll email you about your submission.

                                           **Manage Submission** 

After Clicking "Manage Submission" I filled the little requirements and then I am stuck in

             **Run an automated check for common errors**

Check is in progress. You can leave this page while it's running, if it takes more than a few minutes.

Configured mandatory compliancewebhooks. (Ok working)
Implement an HMAC Signature to verify webhooks. (X Not working)
Used a Valid TLS certificate. (Ok working)

I am stuck in Implement an HMAC Signature to verify webhooks. (X Not working), please someone guide me, it will be more thankful.

app.post('/webhooks/shop/redact',async (req,res)=>{
res.status(200).send({message:'Updated'})
})

Hi Sir/Maam I am new to Shopify App Development, I had devloped my app, and add all the required Webhooks. But when I submit the App on Shopify Partner Dashboad --> All Apps --> AppName --> Distribution --> Shopify App Store listing Attention Draft Help merchants discover your app and how it can help them build their businesses. When you’re ready, submit the app for review. Review wait times vary, but we’ll email you about your submission.

                                           **Manage Submission** 

After Clicking "Manage Submission" I filled the little requirements and then I am stuck in

             **Run an automated check for common errors**

Check is in progress. You can leave this page while it's running, if it takes more than a few minutes.

Configured mandatory compliancewebhooks. (Ok working) Implement an HMAC Signature to verify webhooks. (X Not working) Used a Valid TLS certificate. (Ok working)

I am stuck in Implement an HMAC Signature to verify webhooks. (X Not working), please someone guide me, it will be more thankful.

Getting same error with working webhooks via cli. Let me know if you fix. I was reading around and you need hmac verification on install page. I implemented that and still errors.

Sir I am using Remix framework for Shopify App Development. In which we are using either loader or action function for the post or I think there is no middle ware in Remix. Kindly assist me on this, it will be more thankful.

me too
image

Has anyone been able to resolve this issue.