Webhooks expliqués : signatures et nouvelles tentatives

Backend2026-11-06TryQuickToolBox

Vous avez intégré 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 présentent deux défis majeurs : vérifier que la requête provient bien de l'expéditeur attendu et gérer les échecs lorsque votre point de terminaison est indisponible ou lent. Cet article explique comment implémenter des charges utiles de webhook signées et une logique de nouvelle tentative robuste, avec des exemples de code pratiques.

Que sont les webhooks ?

Un webhook est un rappel 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. Cela rend les intégrations efficaces et quasi temps réel.

Cependant, les webhooks sont basés sur le push, ce qui signifie que votre point de terminaison doit être accessible publiquement, gérer une charge inattendue et faire face aux requêtes en double ou malveillantes. C'est là que la signature et les nouvelles tentatives entrent en jeu.

Pourquoi signer les charges utiles des webhooks ?

Sans vérification, toute personne connaissant l'URL de votre webhook pourrait envoyer de faux événements. La signature des charges utiles avec un secret partagé vous permet d'authentifier l'expéditeur et de garantir que la charge utile n'a pas été falsifiée.

L'approche la plus courante est 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-Signature). Votre serveur recalcule la signature et les compare.

Implémentation de la vérification HMAC

Voici un exemple simple en Node.js avec Express :

const crypto = require('crypto');
const express = require('express');
const app = express();

// Use raw body for signature verification
app.use(express.raw({ type: 'application/json' }));

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-signature'];
  const secret = process.env.WEBHOOK_SECRET;
  const payload = req.body; // 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);
  console.log('Received event:', event.type);
  res.status(200).send('OK');
});

app.listen(3000, () => console.log('Webhook server running'));

Points clés :

Gérer les nouvelles tentatives : rendre les webhooks fiables

Les réseaux échouent, les serveurs plantent et les déploiements provoquent des temps d'arrêt. Un système de webhook fiable doit réessayer les livraisons échouées. Mais des tentatives naïves peuvent entraîner un traitement en double et surcharger votre système.

Stratégies de nouvelle tentative

Les modèles de nouvelle tentative courants incluent :

La plupart des fournisseurs implémentent quelque chose comme : réessayer jusqu'à 5 fois avec un backoff exponentiel sur 24 heures.

Idempotence : la clé de tentatives sécurisées

Étant donné que les tentatives peuvent livrer le même événement plusieurs fois, votre point de terminaison doit être idempotent. Incluez un ID d'événement unique dans la charge utile et stockez les ID traités pour ignorer les doublons.

Exemple utilisant un simple ensemble en mémoire (utilisez une base de données en production) :

const processedEvents = new Set();

app.post('/webhook', (req, res) => {
  // ... signature verification ...
  const event = JSON.parse(payload);
  if (processedEvents.has(event.id)) {
    return res.status(200).send('Already processed');
  }
  // Process event
  processedEvents.add(event.id);
  res.status(200).send('OK');
});

Pour la production, utilisez une base de données avec une contrainte d'unicité sur l'ID d'événement.

Bonnes pratiques pour les consommateurs de webhooks

Comparaison des politiques de nouvelle tentative

Politique Avantages Inconvénients
Intervalle fixe Simple à implémenter Peut surcharger un système en cours de rétablissement
Backoff exponentiel Réduit la charge pendant les pannes Retarde la livraison en cas d'échec transitoire
Backoff exponentiel avec jitter Empêche les tentatives synchronisées Légèrement plus complexe

FAQ

Comment vérifier une signature de webhook ?

Calculez le HMAC du corps brut de la requête à l'aide du secret partagé et comparez-le à l'en-tête de signature à l'aide d'une fonction à temps constant. Ne comparez jamais avec une simple égalité.

Que faire si mon point de terminaison webhook est indisponible ?

Le fournisseur doit réessayer avec un backoff exponentiel. Assurez-vous que votre point de terminaison renvoie rapidement un 2xx et traite les événements de manière asynchrone pour minimiser l'impact des temps d'arrêt.

Puis-je utiliser des webhooks sans signature ?

Ce n'est pas recommandé. Sans signatures, vous ne pouvez pas vérifier l'expéditeur, ce qui rend votre point de terminaison vulnérable aux faux événements. Utilisez toujours des signatures lorsqu'elles sont disponibles.

Lors du test des charges utiles de webhook, vous devrez peut-être inspecter les données JSON. Utilisez le JSON Formatter pour formater et valider rapidement les charges utiles.