How to "stringify" the raw binary data received by a webhook trigger?

Describe the issue/error/question

Hello,

My workflow contains a webhook trigger node that is invoked by an external service, and the HMAC hash of the request body with my API secret is added to one of the request headers.

This HMAC is used to verify the integrity and authenticity of the message. According to the API documentation, I must calculate the HMAC on my own and compare it to the one sent in the request header.

I’m trying hard to make this comparison as it turns out that n8n/nodejs slightly modifies the characters of the JSON representation with respect to the original binary data, which completely modifies the hash, as expected.

I’m not a programmer, so I don’t know if it’s something basic or not, but the fact is I’m a little stuck with it. My need is somehow to take the original binary data from the request and transform it into a string so that I can pass it to a crypto node.

Does anyone have any suggestions for a code snippet for this?

Thank you!

What is the error message (if any)?

Please share the workflow

(Select the nodes and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow respectively)

Share the output returned by the last node

Information on your n8n setup

  • n8n version:
  • Database you’re using (default: SQLite):
  • Running n8n with the execution process [own(default), main]:
  • Running n8n via [Docker, npm, n8n.cloud, desktop app]:

Hi @calaj,
welcome to the cummunity :tada:

You can use the Crypto node to calculate HMAC. To point in the right direction I created a sample workflow using a webhook and checking IF the x-signature header matches the hmac of the stringified json body.

1 Like

Hey Marcus, thank you very much for your quick and kind reply!

Oh, and thanks for the welcome to the community, I just found out about n8n and I’m really excited about all the usage applications that have crossed my mind (let alone the infinite ones that haven’t yet).

Regarding your solution, this is exactly the workflow I implemented before asking for help here on the forum, the problem being that the HMACs just didn’t matched. :grimacing:

After a lot of racking my brains trying to understand why, this is what I did:

1 - I went to the webhook trigger node and enabled the “raw body (binary)” option.

2 - Listened for a test event in this webhook.

3 - In the output received, I clicked on the view button (image below). This showed me a string (which I guess to be the base64 encoding of the received payload, although I didn’t find this clearly in the documentation).

4 - I put the string obtained in step 3 straight into an “online hmac calculator” I found on Google, along with a temporary api secret.

5 - Voila! The HMACs matched perfectly.

So, as I hypothesized in my initial question, I imagine that in the process of transforming the original raw binary body into json and then transforming that back into a string using JSON.stringify, n8n/nodejs slightly alters the still valid representation of the same json, which obviously makes all the difference when calculating the HMAC hash.

My idea then is to somehow use the raw binary data from the body of the request and manipulate it myself so as not to change the original encoded string, but I haven’t been able to do that with my limited programming skills.

Basically what I want to do is the same as n8n does when I click on that view button from item 3, and use the string as is to calculate the HMAC via the crypto node you suggested.

I managed to better explain this now? :grinning:

Hey @calaj,

Can you share the string you got from the post and what you expect the hmac output to be? We can take a guess like @marcus did but if you have already used that raw body option and then the stringify then we will need to see what you are getting and what you are expecting along with the required hmac options and we should be able to sort it out.

Hey @calaj,
can you give the following a shot? I am using the Move Binary Data node to put the binary data into a json field. I am disabling Set All Data so that no json parsing occurs. Do you get the right hmac using this strategy?

1 Like

Hey @marcus , this worked like a charm! Thanks a lot for the help!

To better contextualize what happened, in case anyone sees this topic in the future, apparently the JSON.stringify method doesn’t insert any space characters in its output (perhaps for the sake of data efficiency), whereas the initial raw body contained some space styling, such as the following example data:

Original:

{"entry": [{"id": "0", "time": 1664551596, "changes": [{"field": "description"}]}], "object": "page"}

Stringified:

{"entry":[{"id":"0","time":1664551596,"changes":[{"field":"description"}]}],"object":"page"}

Finally, I have to take my hat off to the elegant simple way this could be solved without any code by @marcus , thanks!

Long live the n8n!

2 Likes