Shopify / shopify-app-template-node

MIT License
892 stars 402 forks source link

How to validate webhooks!! #1252

Open sujalmakkar opened 1 year ago

sujalmakkar commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 7 months ago

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 commented 7 months ago

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 commented 7 months ago

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.

seekpain commented 7 months ago

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 commented 7 months ago

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 commented 6 months ago

me too image

vshalsinghh commented 5 months ago

Has anyone been able to resolve this issue.