Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to validate webhooks!! #1252

Open
sujalmakkar opened this issue Mar 23, 2023 · 9 comments
Open

How to validate webhooks!! #1252

sujalmakkar opened this issue Mar 23, 2023 · 9 comments

Comments

@sujalmakkar
Copy link

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'})
})

@vaught-dawson
Copy link

vaught-dawson commented Apr 10, 2023

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);
...

@StefanoDiLegami
Copy link

I think you can use this function the validateHmac function from shopify-api-js
https://github.com/Shopify/shopify-api-js/blob/3de67ce34d9a85707d00462d9414c2f38fce4f07/docs/reference/utils/validateHmac.md

@urimerhav
Copy link

urimerhav commented May 19, 2023

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.

@Saad-Ahmed-03
Copy link

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.

@Saad-Ahmed-03
Copy link

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.

@Saad-Ahmed-03
Copy link

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.

@yant-ai
Copy link

yant-ai commented Apr 23, 2024

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.

@Saad-Ahmed-03
Copy link

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.

@coderlinbb
Copy link

me too
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants