最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Encoding request body with HMAC sha256 and base64 - Stack Overflow

programmeradmin2浏览0评论

How to encode a request body using HMAC sha 256 and base64.

The request object that i receives from xero webhook.

HEADER:
   "x-xero-signature" : HASH_VALUE
PAYLOAD:
  {
     "events": [],
     "lastEventSequence": 0,
     "firstEventSequence": 0,
     "entropy": "S0m3r4Nd0mt3xt"
  } 

The note from xero documentation says "If the payload is hashed using HMACSHA256 with your webhook signing key and base64 encoded, it should match the signature in the header. This is a correctly signed payload. If the signature does not match the hashed payload it is an incorrectly signed payload."

And I followed this example :

const express = require("express");
const router = express.Router();
const base64 = require('base-64');
const crypto = require('crypto')
const bodyParser = require('body-parser')
const xero_webhook_key = '00fRRlJBYiYN4ZGjmTtG+g/pulyb1Eru68YYL3PFoLsa78dadfQtGrOMuISuVBHxpXeEYo0Yy1Gc+hHMhDkSI/EEcgtrA==';

let options = {
    type: 'application/json'
  };
let itrBodyParser = bodyParser.raw(options);

router.post("/", itrBodyParser, async (req, res, next) =>{
//     console.log('::::WebhookPost:::');
const reSign = req.headers['x-xero-signature'];
 console.log(req.headers['x-xero-signature']);
 console.log('::::::::');
 console.log(req.body);
    console.log("Body: "+JSON.stringify(req.body))
    console.log(req.body.toString());
    console.log("Xero Signature: "+ reSign);
    console.log('Server key::::',xero_webhook_key);
    // Create our HMAC hash of the body, using our webhooks key
    let hmac = crypto.createHmac("sha256", xero_webhook_key).update(req.body.toString()).digest('base64');
    console.log("Resp Signature: ",hmac)

    if (req.headers['x-xero-signature'] == hmac) {
        res.statusCode = 200
    } else {
        res.statusCode = 401
    }
    console.log("Response Code: "+res.statusCode)
    return res.send();
 

});

How to encode a request body using HMAC sha 256 and base64.

The request object that i receives from xero webhook.

HEADER:
   "x-xero-signature" : HASH_VALUE
PAYLOAD:
  {
     "events": [],
     "lastEventSequence": 0,
     "firstEventSequence": 0,
     "entropy": "S0m3r4Nd0mt3xt"
  } 

The note from xero documentation says "If the payload is hashed using HMACSHA256 with your webhook signing key and base64 encoded, it should match the signature in the header. This is a correctly signed payload. If the signature does not match the hashed payload it is an incorrectly signed payload."

And I followed this example : https://devblog.xero./using-xero-webhooks-with-node-express-hapi-examples-7c607b423379

const express = require("express");
const router = express.Router();
const base64 = require('base-64');
const crypto = require('crypto')
const bodyParser = require('body-parser')
const xero_webhook_key = '00fRRlJBYiYN4ZGjmTtG+g/pulyb1Eru68YYL3PFoLsa78dadfQtGrOMuISuVBHxpXeEYo0Yy1Gc+hHMhDkSI/EEcgtrA==';

let options = {
    type: 'application/json'
  };
let itrBodyParser = bodyParser.raw(options);

router.post("/", itrBodyParser, async (req, res, next) =>{
//     console.log('::::WebhookPost:::');
const reSign = req.headers['x-xero-signature'];
 console.log(req.headers['x-xero-signature']);
 console.log('::::::::');
 console.log(req.body);
    console.log("Body: "+JSON.stringify(req.body))
    console.log(req.body.toString());
    console.log("Xero Signature: "+ reSign);
    console.log('Server key::::',xero_webhook_key);
    // Create our HMAC hash of the body, using our webhooks key
    let hmac = crypto.createHmac("sha256", xero_webhook_key).update(req.body.toString()).digest('base64');
    console.log("Resp Signature: ",hmac)

    if (req.headers['x-xero-signature'] == hmac) {
        res.statusCode = 200
    } else {
        res.statusCode = 401
    }
    console.log("Response Code: "+res.statusCode)
    return res.send();
 

});
Share Improve this question edited Apr 27, 2021 at 6:18 Ujjual asked Apr 15, 2021 at 9:26 UjjualUjjual 9982 gold badges13 silver badges36 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 2 +50

Hey I recently did a video on implementing webhooks with Xero, let me know if this gets you unstuck. I found that trying to pass itrBodyParser on the route the way you have wasn't working for me so I switched it with an app.use statement on my specific webhooks endpoint. If you prefer a written guide over video, here's the blog post

I solved it using this solution.! I was using express framework and the request were not getting as raw request also .toString of didn't worked as mentioned in xero documentation.

 const server = http.createServer(async (req, resp) => {
  try {
      console.log(`::::Webhook::: ${webhookPort}`);
      console.log("::::x-xero-signature:::");
      console.log(req.headers["x-xero-signature"]);
      console.log(`--------------------------------------`);
      if (req.method === "POST") {
        if(req.headers["x-xero-signature"]){
          const rData = await new Promise((resolve, reject) => {
            return collectRequestData(req, (result) => {
                
                console.log(result);
                let hmac = crypto
                  .createHmac("sha256", xero_webhook_key)
                  .update(result)
                  .digest("base64");
                  console.log("Resp Signature: ", hmac);
                 
               
                return resolve({
                  hmac,result
                });
              });
          });
           console.log(">>Resp Signature: ", rData);
           console.log('>>x-xero-signature:::',req.headers["x-xero-signature"]);
           if(rData.result){
             const result = JSON.parse(rData.result);
             console.log('result:::',result);
             for(let { resourceId } of result.events) {
              console.log('::INVOICE ID = ',resourceId);
                getInvoiceData(resourceId);
             }
           }

           if(rData.hmac == req.headers["x-xero-signature"] ){
            console.log('::YES');
              resp.statusCode = 200;
          }else{
            console.log('::NO');
            resp.statusCode = 401;
          }
        }
        resp.end();
      }

        console.log("::::Webhookgetsssss:::");
        resp.message = 'Get API'
        resp.end();
     
  } catch (error) {
    resp.statusCode = 200;
    resp.end();
  }
      
     
  });
  server.listen(webhookPort);

function collectRequestData(request, callback) {
    let body = "";
    request.on("data", (chunk) => {
      body += chunk.toString();
    });
    request.on("end", () => {
      callback(body);
    });
  }
发布评论

评论列表(0)

  1. 暂无评论