Vérifier et gérer les webhooks entrants
Authentifiez les événements signés du tableau de bord et les demandes de collecte de secrets partagés sans mélanger leurs formats.
Mis à jour
Sur cette page
Choisissez la bonne méthode de vérification
La mise en œuvre actuelle comporte deux formats de livraison. Les événements de tableau de bord signés incluent Socialjuice-Signature et Socialjuice-Timestamp. Les demandes de formulaire de collecte utilisent plutôt X-Webhook-Secret. Gardez le secret de signature de votre espace uniquement sur le serveur de réception.
Si un en-tête de signature est présent, exigez une vérification HMAC valide. N’acceptez pas une demande signée non valide en tant que demande héritée. Si vous prenez en charge le format de collection, exigez son en-tête de secret partagé exact. Rejeter l'authentification manquante.
Vérifier une demande signée
Lisez le corps brut de la requête avant que le middleware JSON ne le modifie. La signature est HMAC SHA-256 de <timestamp>.<raw_request_body> avec le secret de signature. Socialjuice-Signature contient t=<timestamp>,v1=<hex hmac>. Son horodatage doit correspondre à Socialjuice-Timestamp.
Utilisez une comparaison de résumé en temps constant. Rejetez les en-têtes et les horodatages mal formés datant de plus de cinq minutes dans le passé ou dans le futur. Gardez l'horloge de votre serveur synchronisée. Après vérification, analysez JSON et distinguez webhook.test de testimonial.created.
Exemple HMAC Node.js
Cet exemple vérifie uniquement le format signé. Fournissez le corps brut sous la forme Buffer avant l'analyse JSON. Il n'authentifie pas les demandes de collecte X-Webhook-Secret.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifySocialjuice(rawBody, headers, secret) {
if (!secret || !Buffer.isBuffer(rawBody)) return false;
const timestamp = headers.get('socialjuice-timestamp') || '';
const signature = headers.get('socialjuice-signature') || '';
const match = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(signature);
if (!match || match[1] !== timestamp) return false;
const seconds = Number(timestamp);
if (!Number.isSafeInteger(seconds) ||
Math.abs(Date.now() / 1000 - seconds) > 300) return false;
const expected = createHmac('sha256', secret)
.update(timestamp + '.')
.update(rawBody)
.digest();
const received = Buffer.from(match[2], 'hex');
return expected.length === received.length &&
timingSafeEqual(expected, received);
}Vérifier une demande de recouvrement
Lisez X-Webhook-Secret et comparez-le avec le secret de signature configuré sur votre serveur. Rejetez un en-tête vide ou une incompatibilité. Conservez le point de terminaison sur HTTPS et ne journalisez jamais cet en-tête : sa valeur est le secret lui-même.
Ce format n'inclut pas d'horodatage signé ni d'identifiant de livraison garanti. Il ne peut pas utiliser l'exemple HMAC ci-dessus pour la protection contre la relecture. Inspectez le corps réel, trouvez le témoignage uuid lorsqu'il est disponible et dupliquez-le dans l'espace prévu. Les charges utiles peuvent être plates ou contenir un objet de témoignage imbriqué.
Acceptez rapidement et évitez les travaux en double
Traitez uniquement les demandes authentifiées. Pour les événements signés, dupliquez avec Socialjuice-Delivery ou l'identifiant de l'enveloppe. Pour les demandes de collecte, utilisez un identifiant de témoignage stable lorsqu'il est disponible et conservez le contexte de l'espace de travail. Stockez les enregistrements de déduplication de manière persistante si plusieurs instances de serveur reçoivent des événements.
Renvoyez rapidement une réponse 2xx après avoir accepté une demande en toute sécurité et mis en file d'attente un travail plus lent. Considérez webhook.test comme un test de connexion et non comme un véritable témoignage. La réussite d'un test ne prouve pas que le mappage de la charge utile de votre collection est correct.