Signature HMAC
X-MED-Signature certifie l’authenticité et l’intégrité du corps reçu.Anti-rejeu
X-MED-Timestamp permet de rejeter les requêtes trop anciennes (fenêtre 5 min).Déduplication
X-MED-Delivery-Id identifie une livraison de façon stable pour ignorer les doublons.Les en-têtes de livraison
ChaquePOST sortant vers votre endpoint porte ces quatre en-têtes :
| En-tête | Rôle |
|---|---|
X-MED-Event-Type | Type d’événement (ex. transport.created). |
X-MED-Delivery-Id | Identifiant stable de la livraison — clé de déduplication côté consommateur. Identique sur les retries. |
X-MED-Timestamp | Epoch en secondes au moment de l’envoi — sert à l’anti-rejeu. |
X-MED-Signature | sha256=<hex> — la signature HMAC à vérifier. |
{ id, type, created_at, data }.
Comment la signature est calculée
La valeur de l’en-têteX-MED-Signature est construite ainsi :
Concaténer le payload signé
MED forme la chaîne
{X-MED-Timestamp}.{corps brut} : la valeur de l’en-tête
X-MED-Timestamp, un point littéral ., puis le corps brut de la requête
exactement tel qu’il est transmis sur le réseau.Calculer le HMAC
Un HMAC-SHA256 de cette chaîne est calculé avec votre signing secret
(
whsec_…), encodé en hexadécimal.Le signing secret (
whsec_…) vous est montré une seule fois, à la création de
l’endpoint webhook depuis votre profil client. Conservez-le dans un coffre de secrets :
c’est la clé qui permet de vérifier toutes les signatures de cet endpoint.Le corps brut est impératif
Les deux protections à ne pas oublier
Anti-rejeu — rejeter au-delà de 5 minutes
Anti-rejeu — rejeter au-delà de 5 minutes
Comparez
X-MED-Timestamp (epoch en secondes) à l’heure courante. Si l’écart dépasse
300 secondes (5 minutes), rejetez la requête. Cela empêche un attaquant de capturer
une requête signée valide et de la rejouer plus tard. Inclure le timestamp dans le
payload signé garantit qu’il ne peut pas être falsifié sans invalider la signature.Déduplication — ignorer les livraisons déjà traitées
Déduplication — ignorer les livraisons déjà traitées
La livraison est at-least-once : vous pouvez recevoir plusieurs fois le même
événement (retry après un timeout réseau, par exemple). L’en-tête
X-MED-Delivery-Id
est stable sur tous les essais d’une même livraison. Stockez les IDs déjà traités et
ignorez les doublons — tout en répondant quand même 2xx pour acquitter.Exemple complet — Node.js / Express
L’exemple ci-dessous est complet et exécutable (Node.js ≥ 18). Il capture le corps brut, vérifie l’horodatage anti-rejeu, recalcule le HMAC, compare à temps constant, puis déduplique surX-MED-Delivery-Id.
Comparez toujours la signature avec une fonction à temps constant
(
crypto.timingSafeEqual), jamais avec ===. Une comparaison naïve fuit, par son temps
d’exécution, le nombre d’octets corrects et facilite une attaque par chronométrage.Liste de contrôle
Checklist d'intégration webhook
Checklist d'intégration webhook
- Endpoint exposé en HTTPS uniquement.
- Corps brut capturé (pas de
express.json()avant la vérification). - Signature recalculée sur
{X-MED-Timestamp}.{corps brut}avec le signing secret. - Comparaison à temps constant (
timingSafeEqual). - Horodatage rejeté au-delà de 5 minutes (
X-MED-Timestamp). - Déduplication sur
X-MED-Delivery-Id. - Réponse
2xxrapide pour acquitter ; traitement lourd en asynchrone.
Étapes suivantes
Vue d'ensemble des webhooks
Catalogue complet des événements, en-têtes de livraison, retries et circuit breaker.
Réconciliation
Rattraper les événements manqués avec
GET /events et GET /webhooks/deliveries.