95 lines
2.2 KiB
Markdown
95 lines
2.2 KiB
Markdown
# Webhooks - Verification
|
|
|
|
Verify webhook authenticity and handle URL validation.
|
|
|
|
## Overview
|
|
|
|
Zoom provides two verification mechanisms:
|
|
1. **URL Validation** - Verify your endpoint during setup
|
|
2. **Request Signature** - Verify each webhook request
|
|
|
|
## URL Validation
|
|
|
|
When you configure a webhook endpoint, Zoom sends a validation request:
|
|
|
|
```json
|
|
{
|
|
"event": "endpoint.url_validation",
|
|
"payload": {
|
|
"plainToken": "random_token_string"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Response Required
|
|
|
|
Hash the token with your webhook secret and respond:
|
|
|
|
```javascript
|
|
const crypto = require('crypto');
|
|
|
|
app.post('/webhook', (req, res) => {
|
|
const { event, payload } = req.body;
|
|
|
|
if (event === 'endpoint.url_validation') {
|
|
const hashForValidation = crypto
|
|
.createHmac('sha256', WEBHOOK_SECRET_TOKEN)
|
|
.update(payload.plainToken)
|
|
.digest('hex');
|
|
|
|
return res.json({
|
|
plainToken: payload.plainToken,
|
|
encryptedToken: hashForValidation
|
|
});
|
|
}
|
|
|
|
// Handle other events...
|
|
res.status(200).send();
|
|
});
|
|
```
|
|
|
|
## Request Signature Verification
|
|
|
|
Verify each webhook request is from Zoom:
|
|
|
|
### Headers
|
|
|
|
| Header | Description |
|
|
|--------|-------------|
|
|
| `x-zm-signature` | Request signature |
|
|
| `x-zm-request-timestamp` | Request timestamp |
|
|
|
|
### Verification Code
|
|
|
|
```javascript
|
|
const crypto = require('crypto');
|
|
|
|
function verifyWebhook(req) {
|
|
const signature = req.headers['x-zm-signature'];
|
|
const timestamp = req.headers['x-zm-request-timestamp'];
|
|
// Prefer raw body bytes captured by your framework to avoid JSON re-serialization mismatches.
|
|
const body = req.rawBody ? req.rawBody.toString('utf8') : JSON.stringify(req.body);
|
|
|
|
const message = `v0:${timestamp}:${body}`;
|
|
const hash = crypto
|
|
.createHmac('sha256', WEBHOOK_SECRET_TOKEN)
|
|
.update(message)
|
|
.digest('hex');
|
|
|
|
const expectedSignature = `v0=${hash}`;
|
|
|
|
return signature === expectedSignature;
|
|
}
|
|
```
|
|
|
|
## Security Best Practices
|
|
|
|
1. Always verify signatures
|
|
2. Check timestamp to prevent replay attacks
|
|
3. Use HTTPS endpoints only
|
|
4. Keep webhook secret secure
|
|
|
|
## Resources
|
|
|
|
- **Webhook verification**: https://developers.zoom.us/docs/api/rest/webhook-reference/#verify-webhook-events
|