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. I ended up importing the cryptojs library, because I could not find a way to make this output with the nodes. HMAC needs to be binary before returning to base64, whereas the nodes only return string.
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
Anyone experienced that ? Any suggestions ?
My guess is that the stringify code works only for payloads that have no events, because by debugging the flow, I can see that the last call is the only one with events count > 0. In addition, the 'false' tries are only a letter different than the hash, whereas the try with the events object count > 0 contains a completely different hash against the one I am computing
Is there anyway I can get the raw string body of the HTTP request, instead of a JSON object ? The JSON.Stringify is not returning an identical result (spaces), which means the hash is different and the workaround mentioned above is not working in every case.