Politique de sécurité des webhooks
Kim Giaoui avatar
Écrit par Kim Giaoui
Mis à jour il y a plus d’une semaine

✍️ Signature de l'en-tête

Nous signons les événements du webhook en incluant une signature dans l'en-tête Tomorro_Signature de chaque événement.

Chaque webhook a un secret automatiquement généré et partagé entre Tomorro et l'utilisateur final. Ensuite, pour signer l'événement, nous calculons un HMAC-SHA256 de l'horodatage et du corps de l'événement :

sha256 = HMAC_SHA256(timestamp + "." + eventBody)

Enfin, l'en-tête Tomorro_Signature a le format suivant :

Tomorro-Signature: t=1492774577, sha256=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

avec t l'horodatage et sha256 la clef précédemment calculé.

Notez que les sauts de lignes ont été ajoutés pour plus de clarté, mais un vrai en-tête Tomorro_Signature est sur une seule ligne.

🔍 Vérification de la signature

Quand un client reçoit un événement webhook, il doit vérifier que la signature est valide. Voici un exemple de la façon de le faire :

import {createHmac, timingSageEqual} from 'crypto'; 
function checkSignature(signature, secret, body)
{ const timestamp = signature[0].split('=')[1];
const sig = Buffer.from(signature[1].split('=')[1], 'utf8');
const hmac = createHmac('sha256', secret);
const digest = Buffer.from(hmac.update(timestamp + '.' + JSON.stringify(body)).digest('hex'), 'utf8');
if (sig.length !== digest.length || !timingSafeEqual(digest, sig))
{ return false; }
else { return true; }
}

Notez qu'il est recommandé d'utiliser une comparaison de chaînes de caractères constante dans le temps pour éviter les vulnérabilités liées aux attaques de synchronisation, c'est pourquoi nous utilisons ici timingSafeEqual au lieu de ===

Par ailleurs, le client doit vérifier si la différence entre l'horodatage reçu et l'horodatage courant est dans sa tolérance (ceci afin d'éviter les attaques par rejeu) .

Avez-vous trouvé la réponse à votre question ?