Webhooks expliqués : charges utiles signées et stratégies de réessai

Backend2026-10-19TryQuickToolBox

Vous venez d'intégrer un service tiers qui envoie des webhooks, et tout fonctionne bien en test. Mais en production, vous remarquez des événements manqués occasionnels, des livraisons en double, ou pire, un acteur malveillant envoyant de fausses charges utiles à votre point de terminaison. Les webhooks sont simples en concept mais délicats en pratique. Cet article explique comment sécuriser les webhooks avec des charges utiles signées et mettre en œuvre des stratégies de réessai robustes afin que vous puissiez faire confiance à vos intégrations pilotées par les événements.

Que sont les webhooks et pourquoi ils importent

Les webhooks sont des callbacks HTTP définis par l'utilisateur, déclenchés par des événements spécifiques. Lorsqu'un événement se produit—comme un paiement réussi ou une nouvelle inscription d'utilisateur—le service source envoie une requête HTTP POST à une URL que vous fournissez. Ce modèle basé sur le push est plus efficace que le polling, réduisant la latence et la charge serveur. Cependant, il introduit des défis : vérifier l'authenticité et gérer les échecs de livraison.

Sécuriser les webhooks avec des charges utiles signées

Sans vérification, n'importe qui peut envoyer des requêtes à votre point de terminaison de webhook. Les charges utiles signées résolvent ce problème en incluant une signature cryptographique qui prouve que la requête provient de l'expéditeur de confiance.

Comment fonctionnent les signatures HMAC

La plupart des fournisseurs utilisent HMAC (Hash-based Message Authentication Code) avec un secret partagé. L'expéditeur calcule un hachage de la charge utile en utilisant le secret et l'inclut dans un en-tête (par exemple, X-Signature). Votre serveur recalcule le hachage et le compare. S'ils correspondent, la requête est authentique.

// Exemple : Vérification d'une signature de webhook en Node.js
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(payload);
  const digest = hmac.digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}

Important : Utilisez toujours une comparaison à temps constant pour éviter les attaques temporelles. Vérifiez également la signature par rapport au corps brut de la requête, et non à un objet JSON analysé, car l'analyse peut altérer la charge utile.

Meilleures pratiques pour la vérification de signature

Mettre en œuvre des réessais fiables

Même avec des charges utiles signées, des problèmes réseau ou des pannes temporaires peuvent entraîner l'échec de la livraison des webhooks. Une stratégie de réessai robuste garantit que les événements sont finalement livrés sans surcharger votre système.

Backoff exponentiel avec jitter

Réessayer immédiatement peut aggraver la congestion. Au lieu de cela, utilisez un backoff exponentiel : attendez plus longtemps entre chaque réessai. Ajoutez du jitter (variation aléatoire) pour éviter les problèmes de troupeau tonnant lorsque de nombreux webhooks échouent simultanément.

// Exemple : Calendrier de réessai avec backoff exponentiel et jitter
function getRetryDelay(attempt) {
  const base = 1000; // 1 seconde
  const max = 30000; // 30 secondes
  const delay = Math.min(base * Math.pow(2, attempt), max);
  return delay + Math.random() * 1000; // ajoute jusqu'à 1s de jitter
}

Idempotence : gérer les doublons

Les réessais peuvent entraîner des livraisons en double. Votre gestionnaire de webhook doit être idempotent—traiter le même événement plusieurs fois doit avoir le même effet que le traiter une fois. Utilisez l'ID d'événement de la charge utile pour suivre les événements traités.

Répondez rapidement et accusez réception

Votre point de terminaison de webhook doit répondre avec un code de statut 2xx aussi rapidement que possible—idéalement en quelques secondes. Si le traitement prend plus de temps, mettez l'événement en file d'attente pour un traitement asynchrone et renvoyez 202 Accepted. Cela évite les délais d'attente et les réessais inutiles.

Comparaison : Webhook vs. Polling

Aspect Webhooks Polling
Latence Quasi temps réel Dépend de l'intervalle
Charge serveur Faible (push uniquement) Élevée (requêtes constantes)
Complexité Plus élevée (nécessite des réessais, sécurité) Plus faible
Fiabilité Nécessite une logique de réessai Intrinsèquement fiable

Étape par étape : construire un récepteur de webhook sécurisé

  1. Configurez un point de terminaison HTTPS avec un certificat valide.
  2. Extrayez l'en-tête de signature (par exemple, X-Signature) et l'horodatage.
  3. Vérifiez la signature en utilisant le secret partagé et le corps brut.
  4. Vérifiez l'horodatage pour rejeter les requêtes anciennes (par exemple, plus de 5 minutes).
  5. Analysez la charge utile et vérifiez les ID d'événements en double.
  6. Traitez l'événement de manière asynchrone si nécessaire, et répondez avec 200 OK.
  7. Journalisez l'événement pour l'audit et le débogage.

FAQ

Qu'est-ce qu'une charge utile de webhook signée ?

Une charge utile signée inclut une signature cryptographique (généralement HMAC) qui permet au récepteur de vérifier que la requête provient d'une source de confiance et n'a pas été altérée.

Combien de fois dois-je réessayer un webhook échoué ?

La plupart des systèmes réessaient 3 à 5 fois avec un backoff exponentiel. Ensuite, l'événement est généralement marqué comme échoué et peut nécessiter une intervention manuelle ou une gestion par file d'attente de lettres mortes.

Puis-je utiliser des webhooks sans HTTPS ?

C'est fortement déconseillé. Sans HTTPS, les charges utiles et les signatures peuvent être interceptées ou modifiées. Utilisez toujours TLS pour les points de terminaison de webhook.

Lors du débogage de charges utiles ou de journaux de webhooks, un formatage JSON correct est essentiel. Utilisez notre JSON Formatter pour imprimer joliment et valider rapidement les charges utiles JSON.