Webhooks expliqués : signatures et retries

Backend2026-11-02TryQuickToolBox

Pourquoi les webhooks ont besoin de signatures et de retries

Vous avez créé un endpoint pour recevoir des webhooks d'un fournisseur de paiement ou d'une plateforme SaaS. Tout fonctionne en test, mais en production vous faites face à deux problèmes : comment savoir que la requête provient réellement du fournisseur, et que se passe-t-il si votre serveur est indisponible ou lent ? Sans signatures, n'importe qui peut forger une requête. Sans retries, une simple coupure réseau peut faire perdre un événement définitivement.

Ce guide explique comment implémenter correctement les deux. Nous aborderons la signature HMAC, les étapes de vérification, les stratégies de retry et l'idempotence — les trois piliers d'une gestion fiable des webhooks.

Comment fonctionnent les signatures de webhooks

Une signature de webhook est un hash cryptographique qui prouve que le payload a été créé par quelqu'un qui connaît un secret partagé. La plupart des fournisseurs utilisent HMAC-SHA256. L'émetteur calcule la signature sur le corps brut de la requête (parfois avec un timestamp) et l'inclut dans un en-tête. Le récepteur la recalcule et la compare.

Voici un flux typique :

  1. Le fournisseur et le consommateur partagent une clé secrète (configurée dans le tableau de bord du fournisseur).
  2. Le fournisseur crée le payload, calcule HMAC-SHA256(secret, payload) et l'envoie dans un en-tête comme X-Signature.
  3. Le consommateur reçoit la requête, lit le corps brut, recalcule le HMAC et le compare à l'aide d'une fonction à temps constant.
  4. Si les signatures correspondent, il traite l'événement ; sinon, il rejette avec un code 401.

Important : Utilisez toujours le corps brut de la requête tel que reçu, et non une version parsée puis re-sérialisée. La sérialisation JSON peut modifier les espaces et l'ordre des clés, ce qui casse la signature.

Ajouter des timestamps pour prévenir les attaques par rejeu

Un payload signé seul peut être rejoué par un attaquant qui capture une requête valide. Pour atténuer ce risque, incluez un timestamp dans les données signées et rejetez les requêtes plus anciennes que quelques minutes. Par exemple :

signed_payload = timestamp + "." + raw_body
signature = HMAC-SHA256(secret, signed_payload)

Le consommateur vérifie que le timestamp est dans une fenêtre acceptable (par exemple 5 minutes) et que la signature correspond.

Implémenter la vérification de signature

Regardons un exemple concret en Python avec Flask. Nous allons vérifier une signature envoyée dans l'en-tête X-Signature.

import hmac
import hashlib
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = b'your_shared_secret'

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Signature')
    if not signature:
        abort(401)

    raw_body = request.get_data()
    expected = hmac.new(SECRET, raw_body, hashlib.sha256).hexdigest()

    if not hmac.compare_digest(expected, signature):
        abort(401)

    # Traiter l'événement
    event = request.json
    # ... gérer l'événement ...
    return '', 200

Points clés :

Concevoir une stratégie de retry

Même avec des signatures, les webhooks peuvent échouer : votre serveur peut être indisponible, renvoyer une erreur 500 ou expirer. Les fournisseurs réessaient généralement avec un backoff exponentiel. En tant que consommateur, vous devez également gérer les retries avec élégance.

Voici ce qu'il faut considérer :

La plupart des fournisseurs réessaient sur les réponses non-2xx ou les timeouts, souvent jusqu'à 24 heures avec des intervalles croissants. Consultez la documentation de votre fournisseur pour les détails.

Exemple : gestionnaire d'événements idempotent

Utilisez une table de base de données pour suivre les IDs d'événements traités. Voici un modèle simplifié :

def handle_event(event_id, payload):
    if db.exists('processed_events', event_id):
        return  # déjà traité
    # traiter le payload
    db.insert('processed_events', event_id)
    # ... travail réel ...

Pour un haut débit, utilisez une contrainte d'unicité sur l'ID d'événement et interceptez les erreurs de clé dupliquée.

Comparaison : webhooks signés vs non signés

AspectPayloads signésPayloads non signés
SécuritéVérifie l'authenticité de l'émetteurN'importe qui peut forger des requêtes
Protection contre le rejeuPossible avec des timestampsAucune
Effort d'implémentationModéré (HMAC + vérification du timestamp)Faible
Recommandé pourTous les webhooks en productionTests internes uniquement

Pièges courants et bonnes pratiques

FAQ

Qu'est-ce qu'un payload de webhook signé ?

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

Comment gérer les retries de webhooks sans dupliquer les actions ?

Rendez votre gestionnaire idempotent en suivant les IDs d'événements. Avant de traiter, vérifiez si l'ID a déjà été traité ; si oui, retournez un succès sans répéter le travail.

Puis-je utiliser des webhooks sans signatures ?

Ce n'est pas recommandé pour la production. Sans signatures, vous ne pouvez pas distinguer les requêtes légitimes des requêtes forgées. Vérifiez toujours les signatures lorsqu'elles sont disponibles.

Lors du débogage de payloads de webhooks ou de l'analyse de logs serveur, le JSON Formatter peut vous aider à inspecter et valider rapidement les structures JSON.