简体   繁体   中英

Xero webhooks with Node Red; OK, than not ok

I have been dealing with cryptography craziness since yesterday, I 've literally lost my sleep over this.

I am implementing a node red solution to get webhooks from Xero to be written in a custom app. I have experienced a lot of issues with the payload and how it needs to be stringified and how needs to be hashed, but eventually figured it out thanks to a Github fellow that posted this code to get the body to its 'raw' state

let msgPayloadRaw = JSON.stringify(msg.payload).split(':').join(': ').split(': [').join(':[').split(',"entropy"').join(', "entropy"');

I then create a sha256 base64 hash to check against the header value using the following js code

var cryptojs = context.global.cryptojs;

const webhookKey = 'MyWebhookKeyHere';

let msgPayloadRaw = JSON.stringify(msg.payload).split(':').join(': ').split(': [').join(':[').split(',"entropy"').join(', "entropy"');


let bdata = new Buffer(msgPayloadRaw).toString();

let ciphertext = cryptojs.HmacSHA256(bdata, webhookKey );

let base64encoded = cryptojs.enc.Base64.stringify(ciphertext);


msg.payload = base64encoded;

return msg;

Now everything should work great, but I get a crazy result showcased in this recording, where the web hooks intent status turns to 'OK', and some seconds later returns to this error:

Retry
We haven’t received a successful response on the most recent delivery attempt and will retry sending with decreasing frequency for an overall period of 24 hours.
Response not 200. Learn more
Last sent at 2022-06-22 11:48:28 UTC

What's the problem ?

The problem relies in the http input, where node red parsed the body.

Body needs to be hashed. The body in the http request is like that

{"events":[],"firstEventSequence": 0,"lastEventSequence": 0, "entropy": "IVMMHNWPBAZYRZJRCUAQ"}

Notice the spaces after each :

Node Red converts that body to JSON object. When I do JSON.stringify(msg.payload); I will get the following

{"events":[],"firstEventSequence":0,"lastEventSequence":0, "entropy":"IVMMHNWPBAZYRZJRCUAQ"}

which is obviously the same, but technically it is not (due to spaces) and when hashed it generates a different hash value.

The GitHub fellow did that that walkround

JSON.stringify(msg.payload).split(':').join(': ').split(': [').join(':[').split(',"entropy"').join(', "entropy"');

So in order to solve this, I need to find a way to get the raw http input, instead of the parsed one that node red is providing.

Any ideas how to get the raw input ?

Sort answer: you don't.

The raw body is not available if the Content-Type header is set to application/json the bodyParser will kick in and generate the matching JSON object that is passed as the msg.payload.

the httpNodeMiddleware is attached after the bodyParser so the body has already been changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM