Vérifier la signature HMAC d'un webhook : la bonne méthode

Quiconque connaît — ou devine — l'URL de votre point de terminaison webhook peut envoyer un corps JSON en POST qui ressemble exactement à un vrai événement : même forme, mêmes noms de champs, entièrement faux. La signature comble cette brèche : la preuve qu'une charge utile provient du détenteur du secret partagé, et que rien n'y a été modifié en transit. Stripe, GitHub et la plupart des fournisseurs sérieux signent avec une variation du même schéma HMAC, donc la mécanique ici est presque universelle — l'exemple concret est le propre schéma d'Olmira, réel et actuel, noms d'en-têtes compris.

Ce que HMAC prouve réellement

HMAC (Hash-based Message Authentication Code) part d'un secret que les deux parties connaissent et personne d'autre. L'expéditeur hache la charge utile avec ce secret et joint le résultat ; vous, détenant le même secret, recalculez et comparez. Une correspondance prouve deux choses à la fois : le message vient vraiment de quelqu'un détenant le secret — aucune connaissance de la charge utile ne permet à un attaquant de forger le hash — et rien n'a été modifié après la signature, car changer ne serait-ce qu'un caractère produit un hash complètement différent.

Le schéma exact utilisé par Olmira

Chaque livraison de webhook sortant transporte trois en-têtes : X-Aether-Signature, X-Aether-Webhook-Id et X-Aether-Event. (Le préfixe de l'en-tête indique Aether plutôt que Olmira — un vestige du nom de code interne de la plateforme ; cela ne change rien au fonctionnement du mécanisme, seulement au nom littéral de l'en-tête.)

Vérifier une livraison, en termes clairs

Prenez le corps de requête brut — les octets exacts tels que livrés, avant tout parsing JSON — préfixez-le avec l'horodatage de l'en-tête de signature et un point, calculez le HMAC de cette chaîne avec le secret de votre point de terminaison, et comparez le résultat à la signature livrée en utilisant une comparaison en temps constant. Le module crypto intégré à Node couvre tout cela sans une seule dépendance ; les vérifications préalables ci-dessous sont là où les implémentations correctes se distinguent réellement des cassées.

Les erreurs qui font échouer la vérification

Presque tous les signalements « ma signature ne correspond jamais » se ramènent à un petit nombre de causes. Hacher un corps ré-analysé ou re-sérialisé au lieu des octets bruts exacts est de loin la plus fréquente — les espaces, l'ordre des clés ou le format des nombres peuvent tous changer silencieusement quand un corps passe par un analyseur JSON puis par une re-sérialisation, et le moindre changement produit un hachage différent. Oublier que l'horodatage fait partie de ce qui est signé — hacher le corps seul, sans le préfixe . — est la deuxième plus fréquente, et c'est une erreur facile à commettre parce que le corps est la chose la plus « évidente » à hacher.

Avant de lui faire confiance en production

1

Vérifiez d'abord la fenêtre d'horodatage

Rejetez tout ce qui sort d'une petite tolérance (Olmira publie 300 secondes, soit cinq minutes, comme sa propre valeur de référence) avant de dépenser du temps CPU à calculer une empreinte — une signature périmée ne mérite pas la comparaison.

2

Comparez en temps constant

Utilisez la primitive de comparaison à temps constant de votre langage, et non un simple test d'égalité, pour qu'une non-correspondance ne divulgue jamais d'information temporelle sur la proximité d'une tentative.

3

Vérifiez que vous hachez le corps brut de la requête

Journalisez au moins une fois pendant la configuration la chaîne exacte que votre code s'apprête à hacher, puis comparez-la, octet par octet, à ce qu'une livraison de test a réellement envoyé.

4

Anticipez la rotation du secret

Où que vous stockiez le secret, faites en sorte que sa modification tienne en une ligne de configuration — le faire tourner dans le tableau de bord sans le mettre à jour au même moment fait échouer toutes les livraisons jusqu'à ce que vous rattrapiez le retard.

Comment Olmira gère cela

Chacun des 22 événements webhook d'Olmira — commandes, réservations, paiements, factures, tickets de support et d'autres encore — est signé exactement de la manière décrite ci-dessus, sans exception et sans aucun type d'événement non signé. Chaque endpoint que vous enregistrez reçoit son propre secret indépendant : une fuite sur une intégration ne compromet donc jamais une autre. Avant de passer en production, l'action « Envoyer un test » dans les paramètres de l'endpoint déclenche un envoi d'exemple réel et entièrement signé, par exactement le même chemin de code qu'un événement réel — mêmes en-têtes, même forme d'enveloppe — afin que vous puissiez valider votre vérificateur face au schéma réel sans attendre qu'une véritable commande ou réservation en déclenche un. La plateforme de connecteurs complète dans laquelle tout cela s'inscrit — import CSV, récupérations planifiées et envois entrants aux côtés des webhooks sortants — c'est Intégrations.

Développez l'intégration une fois, faites-lui confiance ensuite

Essai gratuit de 30 jours. Enregistrez un endpoint et envoyez-vous en quelques minutes une vraie livraison de test signée.