Unable to verify zoom's web hook request with Zoom's header

I have been attempting to use the webhook feature to receive real-time updates on recording completion for my Zoom account, but I have encountered a significant issue. Despite following the instructions provided by Zoom, I have been unable to generate the matching signature for verifying the webhook events.

I have thoroughly reviewed the documentation provided by Zoom, when attempting to verify the webhook events with Zoom headers, the signature generated by my system does not match the signature provided by Zoom. As a result, I am unable to verify the authenticity of the webhook events, which makes it impossible to reliably use this feature. Can you please help me into this issue

Technical details:
We are using python 3 and sample code am using is as follows:


import json
import hashlib
import hmac
message = "v0:{}:{}".format(
    request.headers['X-Zm-Request-Timestamp'], 
    json.dumps(request.data, separators=(',', ':'))
)
hash_for_verify = hmac.new(
    secret.encode(),
    msg=message.encode(),
    digestmod=hashlib.sha256
).hexdigest()
signature = "v0={}".format(hash_for_verify)
if signature == request.headers['X-Zm-Signature']:
    print("signatures matched")

Hi @alw.zoom12
Thanks for reaching out to us and welcome to our community!
It has been a while since you posted this, so I am just checking in with you to see if you have been able to troubleshoot this issue or if you still need assistnace from us?

Yes, I am still facing this issue.

I’m facing the same issue, but we are using c#

Thanks for confirming this
Can you confirm that the signature you are generating, matches the headers? @alw.zoom12

Header value doesn’t match with the signature.

Header value doesn’t match with the signature.

Thanks @mpzoomuser and @alw.zoom12
Have you taken a look at our sample app here?

Could you please make sure you are generating the signature correctly

Having the exact same error @elisa.zoom , tried building my own api with fastapi, didn’t work.

I thought maybe was my implementation but no, trying the sample app also didn’t work, seemed like zoom wasn’t sending any request to my url.

Would love to get help on this as this is needed for the service we are building. Don’t know if it has to do with using ngrok that the requests aren’t being sent.

Hi @odynai
You should be able to use ngrok to receive your requests.
Are you still experiencing this issue? have you had any luck by running our sample app?

@elisa.zoom yes yes I am still with the same issue, I don’t receive any request from zoom, it does not even give an error. So I don’t know if its an issue from zoom side.

Tested making a request from my computer to the api as a test and went succesfully

No luck running the sample app followed the exact steps from the tutorial.

There is anything else I can try or do? We really need this and it seems to not be working as intended

Is there a way I can contact you to have assistance with the issue?

Hi @odynai
Could you please verify that you are using the right value for your secret token when running the sample app?
Please note that there are 2 values present in your dashboard :

  • Secret token
  • Verification token

Make sure that you are using the secret token in the sample app when running it

Yes I did use the secret token and didn´t work

@odynai can you try this logic, I just tested it and it works:

app.post('/webhook', (req, res) => {
  const webhookEvent = req.body.event;
  
  if (webhookEvent === 'endpoint.url_validation') {
    const plainToken = req.body.payload.plainToken;
    const hashedToken = crypto.createHmac('sha256', ZOOM_WEBHOOK_SECRET_TOKEN)
                            .update(plainToken)
                            .digest('hex');
    
    const responseJson = {
      plainToken: plainToken,
      encryptedToken: hashedToken
    };
    
    res.status(200).json(responseJson);
  } else {
    // Handle other webhook events here
    console.log('Received webhook:', req.body);

    // Send a response to acknowledge the webhook
    res.sendStatus(200);
  }
});
1 Like

That worked great, thanks