Webhooks expliqués : signatures et tentatives
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. Les webhooks sont la solution standard, mais ils comportent des pièges : des payloads non authentifiés, des événements perdus et des livraisons en double. Cet article explique comment fonctionnent les webhooks, comment signer les payloads pour éviter toute altération, et comment implémenter des retries pour une livraison fiable.
Que sont les webhooks ?
Un webhook est un callback HTTP défini par l'utilisateur. Au lieu que votre application interroge une API pour obtenir des mises à jour, le fournisseur envoie une requête HTTP POST à une URL que vous spécifiez chaque fois qu'un événement se produit. C'est plus efficace et permet des réactions quasi instantanées.
Les cas d'usage courants incluent :
- Notifications de paiement (par exemple, Stripe, PayPal)
- Statut de build CI/CD (par exemple, GitHub, GitLab)
- Plateformes de messagerie (par exemple, Slack, Discord)
- Mises à jour CRM (par exemple, Salesforce)
Pourquoi signer les payloads de webhook ?
Les points de terminaison de webhook sont des URL accessibles publiquement. Sans vérification, n'importe qui peut envoyer de faux payloads, entraînant une corruption des données ou des failles de sécurité. La signature des payloads avec un secret partagé garantit l'authenticité et l'intégrité.
La plupart des fournisseurs utilisent HMAC (Hash-based Message Authentication Code) avec SHA-256. Le fournisseur calcule une signature sur le corps brut de la requête à l'aide d'une clé secrète, et l'inclut dans un en-tête (par exemple, X-Hub-Signature-256). Votre serveur recalcule la signature et la compare.
Comment vérifier une signature
Voici un guide étape par étape :
- Récupérez le corps brut exactement tel qu'envoyé. Ne le parsez pas et ne le modifiez pas avant la vérification.
- Extrayez la signature de l'en-tête.
- Calculez la signature attendue en utilisant HMAC-SHA256 avec votre secret.
- Comparez à l'aide d'une fonction à temps constant pour éviter les attaques temporelles.
Exemple en Node.js :
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const digest = 'sha256=' + hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(signature));
}
En Python :
import hmac
import hashlib
def verify_signature(payload, signature, secret):
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(f'sha256={expected}', signature)
Utilisez toujours une comparaison à temps constant pour éviter toute fuite d'information.
Implémenter des retries pour la fiabilité
Les réseaux échouent, les serveurs redémarrent et les déploiements ont lieu. Un système de webhook robuste doit réessayer les livraisons échouées. Les fournisseurs réessaient généralement avec un backoff exponentiel, mais vous devez également gérer les retries de votre côté.
Stratégies de retry
- Backoff exponentiel : Attendez 1s, 2s, 4s, 8s, etc., entre les tentatives.
- Nombre maximal de tentatives : Limitez les retries pour éviter les boucles infinies (par exemple, 5 tentatives).
- File d'attente de lettres mortes : Après le nombre maximal de tentatives, stockez l'événement pour inspection manuelle.
- Idempotence : Assurez-vous que le traitement du même événement plusieurs fois ne cause pas d'effets secondaires en double.
Clés d'idempotence
De nombreux fournisseurs incluent un ID d'événement unique (par exemple, X-Event-ID). Stockez les ID traités dans une base de données ou un cache pour ignorer les doublons. Par exemple, utilisez Redis avec un TTL pour suivre les ID vus.
Comparaison : Polling vs Webhooks
| Aspect | Polling | Webhooks |
|---|---|---|
| Latence | Dépend de l'intervalle | Quasi temps réel |
| Charge serveur | Élevée (requêtes constantes) | Faible (uniquement sur événements) |
| Complexité | Simple à implémenter | Nécessite un endpoint, sécurité, retries |
| Fiabilité | Manque des événements entre les polls | Peut manquer si l'endpoint est down ; les retries aident |
Meilleures pratiques pour les consommateurs de webhooks
- Répondez rapidement : Retournez un code 2xx en quelques secondes ; traitez de manière asynchrone.
- Validez les signatures : Vérifiez toujours avant de traiter.
- Journalisez tout : Conservez les payloads bruts et les en-têtes pour le débogage.
- Utilisez HTTPS : N'acceptez jamais de webhooks en HTTP simple.
- Surveillez les échecs : Configurez des alertes pour les échecs de retry répétés.
FAQ
Qu'est-ce qu'une signature de webhook ?
Une signature de webhook est un hachage HMAC du payload, créé avec un secret partagé. Elle permet au récepteur de vérifier que la requête provient de l'expéditeur attendu et n'a pas été altérée.
Combien de fois dois-je réessayer un webhook échoué ?
Il n'y a pas de nombre universel, mais 3 à 5 tentatives avec backoff exponentiel est courant. Après cela, journalisez l'événement dans une file d'attente de lettres mortes pour un examen manuel.
Puis-je utiliser des webhooks sans HTTPS ?
Techniquement oui, mais c'est très peu sécurisé. Utilisez toujours HTTPS pour chiffrer les payloads et prévenir les attaques de l'homme du milieu.
Prêt à tester vos endpoints de webhook ? Utilisez notre JSON Formatter pour inspecter et valider rapidement les payloads.