Topics covering webhook creation & management, event handling, Pub/Sub, and Eventbridge, in Shopify apps.
So I have tried multiple different methods to have my webhook requests authenticated here are a few with their errors
router.post("/shopify/webhook", async (req, res) => { try { await validShopifyRequest(shopSecret, req); console.log("Authentic!"); } catch (err) { console.log(err); // Simple example of error handling, this should really go in a log file or something } });
error
{ BadRequestError: request aborted at IncomingMessage.onAborted (/www/tcg/tcgbe/node_modules/valid-shopify-request/node_modules/raw-body/index.js:231:10) at emitNone (events.js:106:13) at IncomingMessage.emit (events.js:208:7) at abortIncoming (_http_server.js:424:9) at socketOnEnd (_http_server.js:440:5) at emitNone (events.js:111:20) at Socket.emit (events.js:208:7) at endReadableNT (_stream_readable.js:1064:12) at _combinedTickCallback (internal/process/next_tick.js:138:11) at process._tickCallback (internal/process/next_tick.js:180:9) message: 'request aborted', code: 'ECONNABORTED', expected: null, length: null, received: 0, type: 'request.aborted' }
async function verifyWebHook(req, res, next) { try { console.log("🎉 We got an order!"); // we'll compare the hmac to our own hash const hmac = req.get("X-Shopify-Hmac-Sha256"); const body = await getRawBody(req); // create a hash using the body and our key const hash = crypto .createHmac("sha256", shopSecret) .update(body, "utf8", "hex") .digest("base64"); // Compare our hash to Shopify's hash if (hash === hmac) { // It's a match! All good console.log("Phew, it came from Shopifify!"); res.sendStatus(200); } else { // No match! This request didn't originate from Shopify console.log("Danger! Not from Shopify!"); res.sendStatus(403); } } catch (e) { console.log(e); } }
sam error as above
TypeError: Data must be a string or a buffer async function verifyWebHook(req, res, next) { try { console.log("🎉 We got an order!"); // we'll compare the hmac to our own hash const hmac = req.get("X-Shopify-Hmac-Sha256"); // create a hash using the body and our key const hash = crypto .createHmac("sha256", shopSecret) .update(req.body, "utf8", "hex") .digest("base64"); // Compare our hash to Shopify's hash if (hash === hmac) { // It's a match! All good console.log("Phew, it came from Shopifify!"); res.sendStatus(200); } else { // No match! This request didn't originate from Shopify console.log("Danger! Not from Shopify!"); res.sendStatus(403); } } catch (e) { console.log(e); } }
ANY HELP IS AWESOME!!!
now im getting the 403 error so im closer
router.post( "/shopify/webhook", bodyParser.json({ verify: function(req, res, buf, encoding) { req.rawBody = buf; } }), validateWebhook, async (req, res) => { console.log("holy **bleep** verified"); } ); function validateWebhook(req, res, next) { let buffme = Buffer.from(JSON.stringify(req.rawBody)); if (Buffer.isBuffer(buffme)) { console.log("BUFFER DIS ASS"); } generated_hash = crypto .createHmac("sha256", shopSecret) .update(buffme) .digest("base64"); if (generated_hash == req.headers["x-shopify-hmac-sha256"]) { next(); } else { console.log("**bleep**"); res.sendStatus(403); } }
My webhook verifying middleware works for me and it looks almost like yours, maybe it'll help:
import * as crypto from 'crypto';
export const verifyWebhook = async ( ctx: AppContext, next: () => Promise<any>, ) => { const shopifyHmac = ctx.request.headers['x-shopify-hmac-sha256']; if (!shopifyHmac) { logError(new Error(), ERROR_MESSAGE.MISSING_SHOPIFY_HMAC, ctx); ctx.throw(400, getStatusText(400)); } const hmac = crypto .createHmac('sha256', process.env.SHOPIFY_API_SECRET) .update(ctx.request.rawBody) .digest('base64'); if (hmac !== shopifyHmac) { logError(new Error(), ERROR_MESSAGE.HMAC_VALIDATION_FAILED, ctx); ctx.throw(400, getStatusText(400)); } await next(); };