Chaque requete webhook inclut un header X-Webhook-Signature contenant un HMAC-SHA256 du body, signe avec votre secret (affiche une seule fois a la creation).
Verification en Node.js
const crypto = require('crypto');
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expected, 'hex')
);
}
// Dans votre handler Express :
app.post('/webhook', (req, res) => {
const sig = req.headers['x-webhook-signature'];
const raw = JSON.stringify(req.body);
if (!verifyWebhook(raw, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Signature invalide');
}
// Traiter l'event...
res.sendStatus(200);
});
Verification en Python
import hmac, hashlib
def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# Flask exemple :
@app.route('/webhook', methods=['POST'])
def handle_webhook():
sig = request.headers.get('X-Webhook-Signature', '')
if not verify_webhook(request.data, sig, WEBHOOK_SECRET):
return 'Signature invalide', 401
# Traiter l'event...
return '', 200