Best practices
Use the raw request body
Always verify the signature using the raw request body.
Do not verify the signature using a parsed JSON object.
Incorrect:
<span><span style="color: undefined">JSON.parse(body)</span></span>
<span><span style="color: undefined">JSON.stringify(parsedBody)</span></span>
<span><span style="color: undefined">Verify signature using the new JSON string</span></span>
<span><span style="color: undefined"></span></span>
Correct:
<span><span style="color: undefined">Read raw body exactly as received</span></span>
<span><span style="color: undefined">Verify signature</span></span>
<span><span style="color: undefined">Then parse JSON</span></span>
<span><span style="color: undefined"></span></span>
Use constant-time comparison
Use a secure comparison function when comparing signatures.
Recommended functions:
| Language | Function |
|---|---|
| Node.js | crypto.timingSafeEqual |
| Python | hmac.compare_digest |
| PHP | hash_equals |
Store processed event IDs
Webhook events can be delivered more than once.
Always store processed event IDs and avoid processing the same event twice.
Example database table:
<span><span style="color: undefined">webhook_event_id</span></span>
<span><span style="color: undefined">processed_at</span></span>
<span><span style="color: undefined">event_type</span></span>
<span><span style="color: undefined"></span></span>
Do not expose the webhook secret
Never expose your webhook signing secret in:
- frontend code;
- mobile applications;
- public repositories;
- logs;
- error reports;
- browser JavaScript.
The webhook secret must remain on your backend server only.
Rotate your webhook secret if needed
If your webhook secret is compromised, rotate it from your MeSomb dashboard.
During rotation, MeSomb may temporarily sign events with both the old and new secrets to avoid breaking your integration.