How to verify Memberstack webhook signatures using the Admin Package without getting header errors? Answered

Post author
Kohlmann Dean

Hey all ๐Ÿ‘‹,

[Admin Package][Webhooks]

I'm currently setting up some webhooks and I'm running into an issue with the Admin Package (node.js) verifyWebhookSignature method. No matter how I pass the headers into the method, I keep getting an error: "Please provide the svix-id, svix-timestamp, and svix-signature headers."

Here is a simplified snippet of my code:

const memberstackAdmin = require('@memberstack/admin');
const memberstack = memberstackAdmin.init(process.env.MEMBERSTACK_API_KEY);

const handleMemberUpdate = async (req, res) => {
try {
const isValid = memberstack.verifyWebhookSignature({
headers: req.headers,
secret: process.env.MEMBERSTACK_WEBHOOK_SECRET,
payload: req.body.payload,
tolerance: 300,
});

if (!isValid) { console.log('Webhook verification failed'); return res.status(400).send('Webhook verification failed'); } } catch (error) { console.log('Verification error:', error.message); return res.status(400).send('Webhook verification failed'); } // More stuffs

};

module.exports = { handleMemberUpdate };

Despite having the svix-id, svix-timestamp, and svix-signature in the headers (which I have confirmed are being present through logging), the verification keeps failing. Any insights or suggestions on what might be going wrong? Do the headers need to be formatted/parsed or something?

In case someone ever runs into this again, the memberstack method expects the header keys to be in all caps despite the headers being sent in lowercase... kind of annoying, but oh well.
ย 
On a similar note, there must be some other discrepancy in how the memberstack.verifyWebhookSignature()ย method expects the payload or other data because I'm running into a similar persistent error:
The signature did not match expected signature for this payload.
I get the error every time despite confirming 1. that the signing secret is correct and passed as a string, 2. the headers are now present (in all caps) and passed exactly as received, and 3. that the payload is passed as an object exactly as received. Is there some kind of expected formatting required for the payload or other parameters?

Thanks in advance for any help!

Comments

2 comments

  • Comment author
    Raquel Lopez

    It took me more time to figure it out that what I'm proud of... but eventually I got it...

    You need to send the whole body of the request req.body instead of req.body.payload

    const secret = 'whsec_' // your webhook secret found in the MS webhook dashboard;
    const headers = {
    "SVIX-ID": req.headers['svix-id'],
    "SVIX-SIGNATURE": req.headers['svix-signature'],
    "SVIX-TIMESTAMP": req.headers['svix-timestamp'],
    }

    try { const isValid = memberstack.verifyWebhookSignature({ headers: headers, secret: secret, payload: req.body, tolerance: 300 }); if (!isValid) { console.error('Webhook verification failed'); return res.status(400).send('Webhook verification failed'); } console.log("webhook verification successfully"); return res.status(200).send('Webhook verification successfully'); } catch (error) { console.error('Verification error:', error.message); return res.status(400).send('Webhook verification failed'); }
    0
  • Comment author
    Kohlmann Dean

    Awesome! It's working as expected now. I see the docs are updated to reflect sending the whole body as well. Thanks for updating that!

    0

Please sign in to leave a comment.