Webhooks expliqués : signatures et stratégies de relance
Vous venez d'intégrer une passerelle de paiement ou un service CI/CD, et vous devez maintenant recevoir des événements en temps réel. Vous avez mis en place un endpoint, mais vous êtes rapidement confronté à deux questions cruciales : comment vous assurer que la requête provient bien du service ? Et que se passe-t-il si votre serveur est indisponible lorsqu'un événement se déclenche ? Cet article répond aux deux en expliquant les payloads signés et les stratégies de relance — le socle de webhooks fiables.
Que sont les webhooks ?
Les webhooks sont des callbacks HTTP définis par l'utilisateur. Lorsqu'un événement se produit dans un système source (par exemple, un nouveau commit, un paiement réussi), il envoie une requête HTTP POST à une URL que vous fournissez. Contrairement au polling, les webhooks poussent les données en quasi temps réel, réduisant la latence et la charge serveur. Cependant, ce modèle push introduit des défis : vérifier l'authenticité et gérer les échecs de livraison.
Pourquoi les payloads signés sont importants
N'importe qui peut envoyer une requête HTTP à votre endpoint. Sans vérification, des attaquants pourraient falsifier des événements, entraînant des actions non autorisées. Les payloads signés résolvent ce problème en incluant une signature cryptographique calculée sur le corps de la requête à l'aide d'un secret partagé. Le récepteur recalcule la signature et la compare, garantissant que le payload n'a pas été altéré et provient bien de l'expéditeur attendu.
Comment fonctionnent les signatures HMAC
La plupart des services utilisent HMAC-SHA256. L'expéditeur crée une signature en hachant le payload avec une clé secrète et l'inclut dans un en-tête (par exemple, X-Signature). Le récepteur fait de même et compare à l'aide d'une fonction à temps constant pour éviter les attaques temporelles.
Étape par étape : vérifier un payload signé
- Extraire la signature de l'en-tête (par exemple,
X-Signature). - Obtenir le corps brut de la requête sous forme de chaîne ou de buffer — ne le parsez pas d'abord, car les changements de formatage cassent la signature.
- Calculer la signature attendue en utilisant HMAC-SHA256 avec votre clé secrète.
- Comparer les signatures à l'aide d'une fonction de comparaison à temps constant.
- Rejeter la requête avec un HTTP 401 si elles ne correspondent pas.
Voici un exemple en Node.js avec Express :
const crypto = require('crypto');
const express = require('express');
const app = express();
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-signature'];
const secret = process.env.WEBHOOK_SECRET;
const payload = req.body; // raw buffer
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}
// Process the event
const event = JSON.parse(payload);
// ... handle event
res.status(200).send('OK');
});
Remarque : utilisez toujours le corps brut pour la vérification. Les middlewares qui parsent le JSON altèrent le payload, provoquant des incompatibilités de signature.
Concevoir une stratégie de relance
Même avec des payloads signés, des problèmes réseau ou des indisponibilités serveur peuvent entraîner des échecs de livraison. Une stratégie de relance robuste garantit que les événements ne sont pas perdus. Points clés :
1. Accuser réception rapidement
Répondez avec un statut 2xx dès que vous avez validé la signature et mis l'événement en file d'attente pour traitement. Cela évite que l'expéditeur ne subisse un timeout et ne relance inutilement.
2. Idempotence
Les relances peuvent livrer le même événement plusieurs fois. Utilisez une clé d'idempotence (souvent incluse dans le payload ou les en-têtes) pour dédupliquer. Stockez les ID d'événements traités et ignorez les doublons.
3. Backoff exponentiel avec jitter
Si votre endpoint renvoie une erreur (non-2xx), l'expéditeur doit réessayer avec des délais croissants. Le backoff exponentiel (par exemple, 1s, 2s, 4s, 8s) réduit la charge pendant les pannes. L'ajout d'un jitter aléatoire évite les problèmes de thundering herd.
Calendrier de relance typique :
| Tentative | Délai |
|---|---|
| 1 | Immédiat |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 heures |
4. File d'attente de messages morts
Après le nombre maximal de relances, déplacez l'événement vers une file d'attente de messages morts pour inspection manuelle. Cela évite les relances infinies et la perte de données.
5. Surveillance et alertes
Suivez les taux de réussite de livraison, la latence et les raisons d'échec. Configurez des alertes pour les pics d'échecs afin de détecter les problèmes tôt.
Pièges courants et bonnes pratiques
- Vérifiez toujours les signatures — ne faites jamais aveuglément confiance aux données entrantes.
- Utilisez HTTPS pour protéger les payloads en transit.
- Renouvelez périodiquement les secrets et prenez en charge plusieurs secrets actifs pendant la rotation.
- Journalisez les événements webhook (avec les données sensibles masquées) pour le débogage.
- Testez avec des payloads d'exemple à l'aide d'outils qui simulent les livraisons de webhooks.
FAQ
Qu'est-ce qu'un payload signé dans les webhooks ?
Un payload signé inclut une signature cryptographique (généralement HMAC) qui permet au récepteur de vérifier l'authenticité et l'intégrité de la requête.
Combien de fois un webhook doit-il être relancé ?
Il n'y a pas de nombre fixe ; les pratiques courantes vont de 3 à 10 relances avec backoff exponentiel. Ensuite, les événements sont souvent envoyés vers une file d'attente de messages morts.
Puis-je utiliser des webhooks sans signatures ?
C'est possible mais fortement déconseillé. Sans signatures, votre endpoint est vulnérable aux requêtes falsifiées et aux fuites de données.
Prêt à tester vos payloads de webhook ? Utilisez notre JSON Formatter pour inspecter et valider rapidement les payloads JSON.