Webhook HMAC hash cannot be verified

Hi everyone! I am trying to verify a webhook using n8n. I have done this dozen of times, however this vendor is somehow different.

I have managed to do the verification process using JavaScript, however I would ideally like to use the Crypto node and not the javascript node. Also, I am not at the moment sure whether the client will self host or use n8n.io to host their n8n instance.

Here is the code that works:

import CryptoJS from 'crypto-js';

// Variables
const vendorWebhookHmacKey = "VENDOR_KEY_ENDING_WITH_EQUAL";
const vendorSignature = "HEADER_SIGNATURE";
const body = '{"EventData":{"personId":"b1","contactType":"PersonalPhone","contactDetail":"2231","internationalDialingCode":"Greece (+30)"},"EventType":"PersonContactDetailChanged","TimeOfCreation":"2024-05-15T11:16:24.7673208Z"}';

// Step 1. Base64 decode the HMAC key generated for the webhook.
const decodedHmacKeyBytes = CryptoJS.enc.Base64.parse(vendorWebhookHmacKey);

// Step 2. Hash the HTTP request body using the decoded HMAC key from step 1, and the HMAC-SHA256 algorithm. The body will be UTF8 encoded.
const hmacSha = CryptoJS.HmacSHA256(body, decodedHmacKeyBytes);

// Step 3. Base64 encode the hash computed in step 2.
const base64EncodedHashedBody = CryptoJS.enc.Base64.stringify(hmacSha);

if {
	vendorSignature === base64EncodedHashedBody
	// OK
}

This works fine, however I cannot recreate the above in the Crypto node.

Here are the instructions from the vendor in this document:

Using Postman

// A Postman Test that calculates the HMAC hash and verifies that it matches the supplied signature
//
// The signature has already been extracted and stored in the "peoplefirst-signature" variable.
// The HMAC key has already been stored in the "PeopleFirstEventStreamHmacKey" variable.
//
let peopleFirstSignature = pm.variables.get("peoplefirst-signature");

pm.test("verify signature", function(){

    let base64EncodedHmacKey = pm.variables.get("PeopleFirstEventStreamHmacKey");
    let decodedHmacKey = CryptoJS.enc.Base64.parse(base64EncodedHmacKey);
    let sha256signature = CryptoJS.HmacSHA256(pm.response.text(), decodedHmacKey).toString(CryptoJS.enc.Base64);

    pm.expect(sha256signature).to.eql(peopleFirstSignature);
});

Using PowerShell

  # A PowerShell script that calculates the HMAC hash and verifies that it matches the supplied signature

  $peoplefirstWebhookHmacKey = "WEBHOOK_HMAC_KEY>"
  $peoplefirstSignature = "WEBHOOK_SIGNATURE"
  $body = 'WEBHOOK_REQUEST_BODY'
  
  
  # Step 1. Base64 decode the HMAC key generated for the webhook.
  $decodedHmacKeyBytes = [System.Convert]::FromBase64String($peoplefirstWebhookHmacKey)
  
  # Step 2. Hash the HTTP request body using the decoded HMAC key from step 1, and the HMAC-SHA256 algorithm. The body will be UTF8 encoded.
  $hmacSha = New-Object System.Security.Cryptography.HMACSHA256
  $hmacSha.key = $decodedHmacKeyBytes
  $hashedBody = $hmacSha.ComputeHash([Text.Encoding]::UTF8.GetBytes($body))
  
  # Step 3. Base64 encode the hash computed in the step 2.
  $base64EncodedHashedBody = [Convert]::ToBase64String($hashedBody)
  
  # Step 4. Compare the base64 encoded value computed in step 3 with the value obtained from the peoplefirst-signature HTTP header.
  if ($base64EncodedHashedBody -eq $peoplefirstSignature)
  {
      Write-Host "Signatures MATCH : " -NoNewline
  }
  else
  {
      Write-Host "Signatures DO NOT MATCH : " -NoNewline
  }
  
  Write-Host "$base64EncodedHashedBody $peoplefirstSignature"
  • n8n version: 1.25.1
  • Database (default: SQLite):n/a
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via: n8n.io
  • Operating system:

It looks like your topic is missing some important information. Could you provide the following if applicable.

  • n8n version:
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app):
  • Operating system:

Hey @stathisaska,

Without having a test hash to verify it is a bit tricky but the example workflow below should work, In the workflow the vendor hmac key is set in the crypto node and if the has doesn’t match the workflow will return a failed message.

Let me know how you get on with this one.

Hi @Jon

Thank you for your help.

I tried it, but it doesn’t work, here is the key 7yKLuuMQC0mAVBzt/LoBoTVT5iD3BNbJ5juCho9aTSQ=

Hey @stathisaska,

Do you have an example body and what the resulting hash should be?

Hey @Jon

Thank you for helping me with this!

Here is the body

{"EventData":{"personId":"317bb1f6-0bf1-4b55-98e5-b1710096c65f","contactType":"PersonalPhone","contactDetail":"23123123","internationalDialingCode":"Greece (+30)"},"EventType":"PersonContactDetailChanged","TimeOfCreation":"2024-05-15T13:13:45.6883894Z"}

Here is the HMAC hash

cUO3ooLBq4Cr5wAkToGcKE8w6SXHvsw6pBxf2kryw38=

Had another play and I can’t get it to match up, I will take another look on Monday morning.

Hey @Jon

Thank you for playing around with this.

I got it to work using the code node