Webhook validation in Javascript/NodeJS

Leandro_Soler
Tourist
16 0 2

Hi,

Does anybody knows how to validate a webhook in Javascript?

I'm not sure if what it is being encoded its the request body as string or how. This is the code I have so far:

const digest = crypto
    .createHmac('SHA256', sharedSecret)
    .update(data)
    .digest('base64');
console.info('isSameDigest', digest, hmac);
return digest === hmac;

"data" in this case its request.body

Thanks

0 Likes
Busfox
Shopify Staff
Shopify Staff
619 48 94

Hi Leandro,

Are you saving data as a utf-8 encoded string? It looks like other people have had success this way. Let me know if you continue to have trouble.

0 Likes
p1016
New Member
2 0 1

Hello:

 

This is the NodeJs that I am using to validate the webhook, and it is not working.  Can you provide any direction?

Thank you in advance.

 

const express = require('express')
const app = express()
const getRawBody = require('raw-body')
const crypto = require('crypto')
const bodyParser = require('body-parser');
const secretKey = 'SECRET KEY'

 

exports.webhookChecker = (req, res) => {
const webhook_hmac = req.get('X-Shopify-Hmac-SHA256')

 

// Create a hash using the body and our key
const hash = crypto
.createHmac('sha256', secretKey)
.update(JSON.stringify(req.body))
.digest('base64')

// Compare our hash to Shopify's hash
if (hash === webhook_hmac) {
// It's a match! All good
console.log('Webhook came from Shopify!');
res.sendStatus(200)
} else {
// No match! This request didn't originate from Shopify
console.log('Danger! Not from Shopify!')
res.sendStatus(403)
}
}

KarlOffenberger
Shopify Partner
1867 182 777

Try with

 

.update(JSON.stringify(req.body), 'utf8')

and also, doing a regular equality check isn't recommended as it leaves you vulnerable to timing attacks. Prefer to use safe-compare when checking the 2 hashes.

 

Looks okay otherwise.

Liked this post? You might also like our fantastic upsell apps Candy Rack and Candy Cart or offer free gifts with Gift Box. All made with ❤️  and care by Digismoothie
0 Likes
p1016
New Member
2 0 1

Thank you Karl.  I tried that, and it is still not working.  I have verified that I am using the correct secret key, I still can't validate the test webhook.  I will implement the safe-compare before I go live, thank you for the suggestion.  

 

The Ruby and PHP examples reference $data, and I am assuming that the this is just what is returned by req.body.  Is there anywhere, that you know of, that I can see exactly what I should be hashing?

0 Likes
KarlOffenberger
Shopify Partner
1867 182 777

Check koa webhook middleware or express equivalent etc. Quite a few of these out in the wild.

Liked this post? You might also like our fantastic upsell apps Candy Rack and Candy Cart or offer free gifts with Gift Box. All made with ❤️  and care by Digismoothie
0 Likes
Conner_Pope
Shopify Partner
33 1 10

I can confirm that I'm getting the same error, I have similar code in my program:

 

verifyHmac(data, hmac) {
if (!hmac) {
return false;
} else if (!data) {
return false;
}
const calculatedSignature = crypto.createHmac('sha256', config.sharedSecret).update(data, 'utf8').digest('base64');
return calculatedSignature === hmac;
},

however, it still doesn't work. Any help :)

wb1
Shopify Partner
39 1 2

You need to use the following. You can validate this by generating a hash in liquid then validating with your function.

<script>
    {% assign my_secret_string = "no can defense the darce" | hmac_sha256: "protect ya neck fool" %}
    console.log('sha256 {{my_secret_string}}')
  </script>

 

function compare_sha256 (inbound_hmac, secret, str) => {
  console.log('secret, str', secret, str)
  var my_hmac = crypto.createHmac('sha256', secret).update(str).digest('hex')
  console.log('inbound_hmac', inbound_hmac, 'my_hmac', my_hmac)
  return inbound_hmac === my_hmac ? true : false
}

 

0 Likes
jsingh
Shopify Partner
4 0 0
    let fnHash = resHeaders["x-shopify-hmac-sha256"];
    let fnBody = JSON.stringify(data.body);
    let secretKey = ""; //  All your webhooks will be signed with 0f009e8f22886da5b5cde06cb34bd7e411c9c1b06519a92800bd303f7188 so you can verify their integrity.
    let finalHash = crypto
        .createHmac('sha256', secretKey)
        .update(fnBody, 'utf8')
        .digest('base64');
    log.info( finalHash, "!-----==========-----", fnHash);

my hash code also not matching for nodejs
Can someone guide me, Am I missing something @Busfox @KarlOffenberger 

0 Likes
Helios
New Member
1 0 1

This one works for me, using express:

// Enable JSON use
app.use(bodyParser.json({
  verify: (req, res, buf) => {
    req.rawBody = buf;
  },
}));

 

Then when compairing:

 const hash = crypto.createHmac('sha256', SHOPIFY_APP_SECRET)
    .update(Buffer.from(req.rawBody, 'utf8'))
    .digest('base64');