Les webhooks sont l'un des moyens les plus puissants de recevoir des mises à jour en temps réel de services tiers. Une seule requête HTTP POST de Stripe, GitHub, Shopify ou Twilio peut déclencher une logique métier critique dans votre application — facturer un client, mettre à jour un dépôt, expédier une commande ou envoyer un SMS de confirmation.
Mais chaque requête de webhook arrive via l'internet public. Et cela signifie que toute personne qui devine ou découvre votre URL de webhook peut envoyer des charges utiles malveillantes qui semblent parfaitement légitimes. Sans une authentification appropriée, votre application n'a aucun moyen de faire la différence entre un événement réel et un événement falsifié.
C'est là qu'intervient la vérification de la signature de webhook. Il s'agit d'un mécanisme simple et standardisé qui garantit que chaque requête de webhook entrante provient réellement du service attendu et n'a pas été altérée pendant le transit.
Dans ce guide complet, vous apprendrez exactement comment fonctionne la vérification de la signature de webhook, et comment l'implémenter correctement dans les langages populaires. Vous découvrirez également les erreurs courantes à éviter et comment tout tester de bout en bout — rapidement et de manière fiable.
Qu'est-ce que la vérification de signature de Webhook ?
La vérification de signature de webhook est le processus de confirmation qu'une requête de webhook entrante provient réellement du service que vous attendez et n'a pas été altérée.
La plupart des fournisseurs utilisent HMAC (Hash-based Message Authentication Code) avec SHA-256 ou SHA-512. Le service calcule :
signature = HMAC-SHA256(secret_key, payload)
Ensuite, ils envoient la signature dans un en-tête (généralement X-Signature, Signature, ou X-Hub-Signature-256).
Votre serveur :
- Reçoit la charge utile sous forme d'octets bruts (important !)
- Recalcule le HMAC en utilisant votre secret stocké
- Compare la signature calculée avec celle reçue
Si elles correspondent exactement, vous traitez le webhook. Sinon, vous renvoyez HTTP 401 ou 403.
Pourquoi HMAC-SHA256 est le standard de l'industrie
Les fournisseurs choisissent HMAC-SHA256 pour de bonnes raisons :
- Rapide : Même sur du matériel modeste, c'est extrêmement rapide.
- Sécurisé : SHA-256 reste inviolable en 2025.
- Simple : Une seule clé secrète, pas de paires de clés publiques/privées à gérer.
- Standardisé : Des bibliothèques dans tous les langages l'implémentent correctement.
GitHub, Stripe, Shopify, Slack et des dizaines d'autres utilisent tous HMAC-SHA256.
Comment implémenter la vérification de signature de webhook en Node.js
Commençons par un exemple concret en Node.js.
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const computedSignature = hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(computedSignature),
Buffer.from(signature)
);
}
Points clés à noter :
- Utilisez toujours
crypto.timingSafeEqualpour éviter les attaques par chronométrage. - N'utilisez jamais
===sur des chaînes de caractères — c'est vulnérable. - Utilisez
Buffer.from()pour garantir une comparaison à temps constant.
Exemple de middleware Express :
app.post('/webhooks/stripe', (req, res, next) => {
const signature = req.headers['stripe-signature'];
const secret = process.env.STRIPE_WEBHOOK_SECRET;
// Obtenir le corps brut (Express a besoin d'un middleware pour préserver le corps brut)
const rawBody = req.rawBody || req.body; // utiliser body-parser avec l'option verify
if (!verifyWebhookSignature(rawBody, signature, secret)) {
return res.status(401).send('Invalid signature');
}
// La signature est valide → traiter l'événement
next();
});
Implémentation Python (FastAPI + Pydantic)
from fastapi import FastAPI, Request, HTTPException
import hmac
import hashlib
app = FastAPI()
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
computed = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(computed, signature)
@app.post("/webhooks/github")
async def github_webhook(request: Request):
signature = request.headers.get("X-Hub-Signature-256")
if not signature:
raise HTTPException(status_code=401, detail="Signature manquante")
payload = await request.body()
if not verify_signature(payload, signature.split('=')[1], SECRET):
raise HTTPException(status_code=401, detail="Signature invalide")
# Traiter le webhook
return {"status": "ok"}
Pièges courants des développeurs (et comment les éviter)
1. Utiliser JSON.stringify() ou un corps analysé
De nombreux frameworks analysent automatiquement le JSON. Cela interrompt la vérification car les espaces blancs, l'ordre des clés et le formatage peuvent différer.
Solution : Capturez toujours le corps brut avant de l'analyser.
Dans Express : Utilisez body-parser avec { verify: true }
Dans FastAPI : Utilisez await request.body()
2. Comparer des chaînes avec ===
Les attaques par chronométrage peuvent divulguer des informations. Utilisez crypto.timingSafeEqual ou hmac.compare_digest.
3. Stocker les secrets dans le code
Utilisez des variables d'environnement ou des gestionnaires de secrets (AWS Secrets Manager, HashiCorp Vault, etc.).
4. Oublier de gérer les attaques par rejeu
La plupart des fournisseurs incluent un horodatage. Vérifiez que l'événement est récent (par exemple, dans les 5 minutes).
const timestamp = req.headers['X-Signature-Timestamp'];
if (Date.now() - timestamp > 5 * 60 * 1000) {
return res.status(401).send('Horodatage trop ancien');
}
5. Utiliser SHA-1 (cela arrive encore !)
GitHub a déprécié SHA-1 en 2022. Utilisez toujours SHA-256.
Tester la vérification de signature de webhook avec Apidog
Tester manuellement les webhooks est fastidieux. Vous envoyez une requête, vérifiez les logs, corrigez, répétez.
Apidog rend cela trivial :
Dans votre projet Apidog, cliquez sur l'icône + dans la barre latérale gauche et choisissez "Autres API de protocole" > "Webhook".
Après avoir créé le Webhook, remplissez les champs suivants dans l'éditeur :Méthode de requête : Généralement POST.Nom du Webhook : Ce nom apparaîtra dans la documentation de l'API et l'exportation OpenAPI, par exemple, order.URL de débogage (facultatif) : L'URL réelle utilisée pour l'envoi des requêtes de test. Note : Ceci est uniquement à des fins de test et ne sera pas inclus dans la documentation.Autres informations : Telles que le corps de la requête.
Cliquez sur Enregistrer une fois que vous avez rempli tous les champs requis.
Il suffit d'entrer votre URL de Webhook dans le champ URL de débogage, puis de cliquer sur Envoyer pour simuler un appel de Webhook.
J'ai économisé des heures de débogage avec le simulateur de webhook d'Apidog. Il prend même en charge le format exact stripe-signature de Stripe et le préfixe sha256=... de GitHub.
Exemple réel : Vérifier les Webhooks Stripe
Stripe utilise un format d'en-tête spécial :
stripe-signature: t=1681234567,v1=abc123...,v0=def456...
Vous devez :
- Extraire l'horodatage
t= - Extraire la signature
v1=(préférable) - Recalculer en utilisant
payload + timestamp - Comparer uniquement la partie
v1
Stripe fournit des bibliothèques officielles pour gérer cette complexité :
const stripe = require('stripe')('sk_...');
stripe.webhooks.constructEvent(payload, sigHeader, endpointSecret);
Mais comprendre le HMAC sous-jacent est crucial lorsque vous devez l'implémenter vous-même.
Sujets avancés : Tolérer plusieurs signatures
Certains fournisseurs (comme Stripe) envoient plusieurs signatures pour des raisons de compatibilité ascendante. Votre code devrait :
- Diviser l'en-tête par
, - Essayer chaque signature
- Accepter si l'une d'entre elles correspond
Bonnes pratiques de sécurité en 2025
- Renouveler les secrets de webhook tous les 90 jours.
- Utiliser des secrets de courte durée si possible.
- Enregistrer les vérifications échouées mais ne jamais enregistrer le secret.
- Limiter le taux d'accès aux points de terminaison des webhooks pour prévenir les attaques par force brute.
- Toujours utiliser HTTPS.
Conclusion : Petite étape de vérification, grand gain de sécurité
La vérification de signature de webhook peut sembler un détail mineur. Mais c'est la différence entre une application sécurisée et une application que les attaquants peuvent facilement exploiter.
Implémentez-la correctement, testez-la minutieusement avec des outils comme Apidog, et dormez tranquille en sachant que vos intégrations sont protégées.
Téléchargez Apidog gratuitement dès aujourd'hui et vérifiez votre premier webhook en moins de 5 minutes. C'est le moyen le plus rapide de prouver que votre code fonctionne réellement.
