Have your say in Community Polls: What was/is your greatest motivation to start your own business?

App failing hmac verification for webhook

App failing hmac verification for webhook

vscode
Shopify Partner
9 3 0

vscode_0-1718356865496.png

Hi, My node app is failing the hmac verification for mandatary webhooks. Is there a solution for this problem.


this is the code for webhook in my app

app.post(
  shopify.config.webhooks.path,
  shopify.processWebhooks({ webhookHandlers: PrivacyWebhookHandlers })
 
);


I have looked almost everywhere and wasted a lot of time on this, Please help out if you know a solution or a workaround for this.

Replies 2 (2)

BrainStation23
Shopify Partner
413 62 60

hi @vscode,

To verify the payload sent from Shopify you need to match the hash of the request body from the webhooks payload. 
Keep in mind the request body has to be the raw buffer from the HTTP request before getting parsed by body parser or any json parser. I made a middleware that passes the raw buffer along with the parsed body to my middleware layer. you need the client secret of your app to calculate the hash from the raw request body.
Shopify gives you the hash value you should expect in the header as "X-Shopify-Hmac-Sha256". You need to compare your calculated hash value a the hmac given from Shopify end.

I'm sharing my hmac verification code below

Pass the raw body along with the parsed body

this.express.use(
            '/api/webhook',
            express.raw({ type: 'application/json' }),
            (req: RawBodyRequest, res: Response, next: NextFunction) => {
                req.rawBody = req.body;
                req.body = JSON.parse(req.body);
                next();
            }
        );

 
get hmac from request header

async function webhookMiddleware(
    req: RawBodyRequest,
    res: Response,
    next: NextFunction
): Promise<Response | void> {
    try {
        const shopUrl = req.headers['x-shopify-shop-domain'];
        const shopifyHmac = req.headers['x-shopify-hmac-sha256'] as string;

        if (!shopUrl || !shopifyHmac)
            throw new HttpException(400, 'Invalid request headers');
        if (!req.rawBody) throw new HttpException(400, 'Invalid request body');
        
        # Business logic

        if (!verifyHmac(req.rawBody, shopifyHmac, apiSecrate))
            throw new HttpException(400, 'Unauthorized request');

        # Business logic

        next();
    } catch (error: any) {
        return res.status(404).json({
            status: 404,
            message: error.message || 'Something went wrong!',
        });
    }
}

 

Varify hmac

function verifyHmac(bodyBuffer: Buffer, hmac: string, apiSecrate: string) {
    const calculatedHmac = crypto
        .createHmac('sha256', apiSecrate)
        .update(bodyBuffer)
        .digest('base64');
    return calculatedHmac === hmac;
}


I'm adding Shopify's documentation pages link below
Webhook docs - Shopify 
Verify webhooks -Shopify 

Brain Station 23 PLC (Mail: js.sbu@brainstation-23.com)
- Was your question answered? Mark it as an Accepted Solution
- Did the solution not address your concern? We kindly request that share or mail your store URL with us this will enable us to collaborate more closely.
- Explore our Shopify public apps
vscode
Shopify Partner
9 3 0

Does this work with shopify's node template that uses shopify.processWebhooks({ webhookHandlers: PrivacyWebhookHandlers }) to process the webhooks?