Aller au contenu

Vérification de signature

Chaque requête webhook envoyée par Sangho contient un header Sangho-Signature. Ce header est une signature HMAC-SHA256 calculée avec votre webhook secret sur le corps brut de la requête.

Pourquoi vérifier la signature

  • Garantir que la requête provient bien de Sangho.
  • Se protéger contre les attaques par rejeu (replay attacks).
  • Valider l'intégrité du corps de la requête.
  • Prévenir le traitement de webhooks falsifiés.

Format du header

Le header Sangho-Signature contient la signature HMAC-SHA256 du corps en hexadécimal, préfixée de sha256=. Deux headers complémentaires sont également envoyés :

HeaderDescription
Sangho-Signaturesha256=<hex> — signature HMAC du corps brut.
Sangho-Event-IDIdentifiant unique de l'événement — utilisez-le pour la déduplication.
Sangho-TimestampTimestamp Unix de l'envoi — protège contre les replays.
Utilisez toujours le corps brut

La signature est calculée sur le corps brut (raw bytes) de la requête, avant tout parsing JSON. En Express.js, configurez express.raw({ type: 'application/json' }) — ne passez jamais par express.json() qui transformerait le body avant vérification.

Bonnes pratiques

  • Vérifier la signature avant de traiter l'événement.
  • Retourner HTTP 200 immédiatement — traiter en arrière-plan.
  • Stocker le Sangho-Event-ID pour dédupliquer les livraisons multiples.
  • Comparer les signatures avec une méthode résistante aux timing attacks (timingSafeEqual, hmac.compare_digest, hash_equals).

Headers d’une requête webhook

Response Exemple de requête entrante
Headers envoyés par Sangho à votre endpoint à chaque événement.
http
POST /webhook HTTP/1.1
Content-Type: application/json
Sangho-Signature: sha256=a2b3c4d5e6f7...
Sangho-Event-ID: evt_xxxxxxxxxxxx
Sangho-Timestamp: 1709294400

Vérification manuelle (openssl)

bash
echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -hex
# Comparer avec la valeur dans Sangho-Signature (sans le préfixe sha256=)

Implémentation par langage

Chaque exemple ci-contre illustre la vérification complète : lecture du corps brut, calcul HMAC-SHA256, comparaison résistante aux timing attacks, puis parsing JSON.

Pour les SDKs officiels, utilisez directement la méthode helper : sangho.webhooks.constructEvent(body, signature, secret) en javascript/JavaScript.

Répondez vite, traitez en async

Votre endpoint doit retourner un 200 dans les 30 secondes. Enfilez la tâche dans une queue asynchrone (Celery, Bull, Sidekiq…) et répondez immédiatement. Passé ce délai, Sangho considère la livraison comme échouée et déclenche la politique de retry.

Implémentation par langage

javascript
import express from 'express';
import crypto from 'crypto';


const app = express();


app.post(
  '/webhook',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const sig    = req.headers['sangho-signature'] as string;
    const secret = process.env.WEBHOOK_SECRET!;


    const expected = 'sha256=' + crypto
      .createHmac('sha256', secret)
      .update(req.body)
      .digest('hex');


    if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
      return res.status(400).send('Signature invalide');
    }


    const event = JSON.parse(req.body.toString());
    // Traiter en arrière-plan, répondre immédiatement
    processEvent(event).catch(console.error);
    res.json({ received: true });
  },
);