# Unable to verify webhook signature (NodeJS)

**URL:** <https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524>\
**Category:** ⚙️ API\
**Tags:** collect-api, payments\
**Created:** [September 21, 2022, 12:38pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524 "2022-09-21T12:38:30Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![eni4sure](https://sea2.discourse-cdn.com/flex016/user_avatar/community.rapyd.net/eni4sure/32/20794_2.png) [@eni4sure](https://community.rapyd.net/u/eni4sure)\
**Post date:** [September 21, 2022, 12:38pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/1 "2022-09-21T12:38:30Z")

</div>

Hello everyone!

I have a question related Rapyd webhook. I want to verify the signature get from webhook.

The signature i calculate is always different from the webhook.

```auto
async verifyWebhookSignature(signatureReceived, salt, timestamp, body) {
    // webhook url path set in dashboard.
    const webhookUrlPath = RAPYD.WEBHOOK_URL;
    // access key from dashboard.
    const accessKey = RAPYD.ACCESS_KEY;
    // secret key from dashboard.
    const secretKey = RAPYD.SECRET_KEY;
    // stringified JSON string without whitespace
    const bodyString = JSON.stringify(body);

    // Signature
    const informationToSign = webhookUrlPath + salt + timestamp + accessKey + secretKey + bodyString;
    const signedData = CryptoJS.enc.Hex.stringify(CryptoJS.HmacSHA256(informationToSign, secretKey));
    const finalSignature = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(signedData));

    // If the finalSignature is equal to signature received, return true
    if (finalSignature == signatureReceived) return true;

    return false;
}

```

---

<div class="post-metadata">

**Author:** ![Benrobo](https://sea2.discourse-cdn.com/flex016/user_avatar/community.rapyd.net/benrobo/32/5121_2.png) [@Benrobo](https://community.rapyd.net/u/Benrobo)\
**Post date:** [September 21, 2022, 4:03pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/2 "2022-09-21T16:03:41Z")

</div>

Hope this helps.

```auto
function sign(method, urlPath, salt, timestamp, body) {
    try {
        let bodyString = "";
        if (body) {
            bodyString = JSON.stringify(body);
            bodyString = bodyString == "{}" ? "" : bodyString;
        }

        let toSign =
            method.toLowerCase() +
            urlPath +
            salt +
            timestamp +
            accessKey +
            secretKey +
            bodyString;
        log && console.log(`toSign: ${toSign}`);

        let hash = crypto.createHmac("sha256", secretKey);
        hash.update(toSign);
        const signature = Buffer.from(hash.digest("hex")).toString("base64");
        log && console.log(`signature: ${signature}`);

        return signature;
    } catch (error) {
        console.error("Error generating signature");
        throw error;
    }
}

```

---

<div class="post-metadata">

**Author:** ![eni4sure](https://sea2.discourse-cdn.com/flex016/user_avatar/community.rapyd.net/eni4sure/32/20794_2.png) [@eni4sure](https://community.rapyd.net/u/eni4sure)\
**Post date:** [September 21, 2022, 4:36pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/3 "2022-09-21T16:36:11Z")

</div>

Thanks, but your solution here is only valid for creating a signature (which I don’t have a problem with)

Interested in the verification part for webhook signatures.

---

<div class="post-metadata">

**Author:** ![Benrobo](https://sea2.discourse-cdn.com/flex016/user_avatar/community.rapyd.net/benrobo/32/5121_2.png) [@Benrobo](https://community.rapyd.net/u/Benrobo)\
**Post date:** [September 21, 2022, 5:46pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/4 "2022-09-21T17:46:07Z")

</div>

Yh sure, have you tried using raw body passed in without stringifying it.

```auto
getWebhookSignature(webhookUrl: string, saltHeader: string, timestampHeader: string, rawBody: string) {
    return (
      Buffer.from(
        crypto.createHmac('sha256', this.secretKey)
          .update(webhookUrl)
          .update(saltHeader)
          .update(timestampHeader)
          .update(accessKey)
          .update(secretKey)
          .update(rawBody)
          .digest('hex')
      ).toString('base64')
    );
  }

```

And see if it matches the signature sent from from the webhook

---

<div class="post-metadata">

**Author:** ![Benrobo](https://sea2.discourse-cdn.com/flex016/user_avatar/community.rapyd.net/benrobo/32/5121_2.png) [@Benrobo](https://community.rapyd.net/u/Benrobo)\
**Post date:** [September 21, 2022, 6:34pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/5 "2022-09-21T18:34:19Z")

</div>

you can also try to check how you are parsing the body…

same rules apply as the ones for the api requests.

---

<div class="post-metadata">

**Author:** ![eni4sure](https://sea2.discourse-cdn.com/flex016/user_avatar/community.rapyd.net/eni4sure/32/20794_2.png) [@eni4sure](https://community.rapyd.net/u/eni4sure)\
**Post date:** [September 21, 2022, 6:36pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/6 "2022-09-21T18:36:28Z")

</div>

Hey man, still doesn’t work ☹

---

<div class="post-metadata">

**Author:** ![Benrobo](https://sea2.discourse-cdn.com/flex016/user_avatar/community.rapyd.net/benrobo/32/5121_2.png) [@Benrobo](https://community.rapyd.net/u/Benrobo)\
**Post date:** [September 21, 2022, 6:44pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/7 "2022-09-21T18:44:24Z")

</div>

Huhh. Ok, as stated by the Rapyd team, if it doesn’t work, try contacting them @

[https://support.rapyd.net/](https://support.rapyd.net/)

They should be able to respond to the above problem stated.

---

<div class="post-metadata">

**Author:** ![Community\_Team](https://avatars.discourse-cdn.com/v4/letter/c/46a35a/32.png) [@Community\_Team](https://community.rapyd.net/u/Community_Team)\
**Post date:** [September 21, 2022, 11:03pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/8 "2022-09-21T23:03:57Z")

</div>

Thanks for asking @eni4sure, and thanks for your help @Benrobo.

I would definitely reach out to support.

In the meantime you can view some of these past topics about correcting the body string of the signature request to match the webhook.

> [@How to verify Webhook Signature with PHP script](https://community.rapyd.net/t/how-to-verify-webhook-signature-with-php-script/1382/4):
>
> Thanks @Ha_Tr_n, how’s it going? Have you tried using the [Request Signatures](https://docs.rapyd.net/build-with-rapyd/reference/message-security#request-signatures) example: $body = array(); // JSON body goes here. Always empty for GET; // strip nonfunctional whitespace. $body\_string = json\_encode($body); Compared to: $body = $request-\>all(); $bodyString = $body && !is\_null($body) ? json\_encode($body, JSON\_UNESCAPED\_SLASHES) : '';

> [@Verify Webhook Signature?](https://community.rapyd.net/t/verify-webhook-signature/1383):
>
> Hello everyone! I have a question related Rapyd webhook. I want to verify the signature get from webhook. I am PHP Developer and this is my code: \<?php $access\_key = 'access-key'; // get from Dashboard $secret\_key = 'secret-key'; // get from Dashboard $salt = 'epiAT7douEg/9ezxZzoByA=='; // get from webhook header $timestamp = 1642058448; // get from webhook header $signature\_from\_webhook = 'base-64-value'; // get from webhook header // Data from payment hook https://docs.rapyd.net/build-with…

---

<div class="post-metadata">

**Author:** ![eni4sure](https://sea2.discourse-cdn.com/flex016/user_avatar/community.rapyd.net/eni4sure/32/20794_2.png) [@eni4sure](https://community.rapyd.net/u/eni4sure)\
**Post date:** [September 21, 2022, 11:26pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/9 "2022-09-21T23:26:06Z")

</div>

Tried reaching the support but it requires me to login ? and I don’t know where to signup.

 ![image](https://us1.discourse-cdn.com/flex016/uploads/rapyd/original/3X/a/a/aa73613ef9ac0f5ad143d3c8e3d7726221badf4e.jpeg)

---

<div class="post-metadata">

**Author:** ![eni4sure](https://sea2.discourse-cdn.com/flex016/user_avatar/community.rapyd.net/eni4sure/32/20794_2.png) [@eni4sure](https://community.rapyd.net/u/eni4sure)\
**Post date:** [September 21, 2022, 11:27pm UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/10 "2022-09-21T23:27:35Z")

</div>

Yes I’ve seen this, it’s implemented in PHP.  
Though, I’ve tried following the instructions for JS but it still doesn’t work!

---

<div class="post-metadata">

**Author:** ![Community\_Team](https://avatars.discourse-cdn.com/v4/letter/c/46a35a/32.png) [@Community\_Team](https://community.rapyd.net/u/Community_Team)\
**Post date:** [September 22, 2022, 4:33am UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/11 "2022-09-22T04:33:13Z")

</div>

Thanks, it’s in PHP, but the issue may be the same with the spacing in the body string.

Here is also a helpful video by @Community_Team

[![](https://us1.discourse-cdn.com/flex016/uploads/rapyd/original/3X/f/e/fe7f5c3d772115b3d1ca892aaa791bd8da58eecc.jpeg "Rapyd Integrations: Request Signatures and How to Calculate") ](https://www.youtube.com/watch?v=IUqDc4Siq70)

You can use your [Client Portal login](https://dashboard.rapyd.net/login) for the support login, not to the Developer Community Forum.

---

<div class="post-metadata">

**Author:** ![eni4sure](https://sea2.discourse-cdn.com/flex016/user_avatar/community.rapyd.net/eni4sure/32/20794_2.png) [@eni4sure](https://community.rapyd.net/u/eni4sure)\
**Post date:** [September 22, 2022, 4:49am UTC](https://community.rapyd.net/t/unable-to-verify-webhook-signature-nodejs/57524/12 "2022-09-22T04:49:24Z")

</div>

I’ve checked the body and parsed it via JSON.stringify(body) to remove extra space. Still no solution ☹
