nouko.
Documentation développeurs
Docs / Vérifier la signature

Vérifier la signature des webhooks

Vérifiez l’en-tête Nouko-Signature (HMAC-SHA256) en Node.js, Python, PHP, Go, Java et Ruby, avec les pièges à éviter.

MarkdownOpenAPI

Chaque webhook porte l’en-tête Nouko-Signature: t=<horodatage>,v1=<signature>. Vérifiez-le avant de faire confiance au contenu.

v1 = hex( HMAC-SHA256( secret_du_webhook, t + "." + corps_brut ) )
  1. Séparez t et v1 dans l’en-tête.
  2. Refusez si t est éloigné de plus de 300 secondes (5 minutes) de l’heure actuelle.
  3. Calculez le HMAC sur t + "." + corps_brut avec votre secret.
  4. Comparez en temps constant avec v1.
import crypto from 'node:crypto';

// rawBody : le corps EXACT reçu (Buffer ou string), avant tout JSON.parse
export function verifyNouko(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map(p => p.trim().split('=')));
  if (!parts.t || !parts.v1) return false;
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = crypto.createHmac('sha256', secret)
    .update(parts.t + '.').update(rawBody).digest('hex');
  const a = Buffer.from(expected), b = Buffer.from(parts.v1);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Pièges fréquents

  • Corps re-sérialisé : signez le corps exact reçu, pas JSON.stringify(JSON.parse(body)). Désactivez le parseur JSON automatique sur cette route.
  • Horloge décalée : synchronisez votre serveur (NTP), sinon les messages valides sont refusés.
  • Mauvais secret : chaque adresse webhook a son propre secret ; sandbox et production sont différents.
  • Comparaison simple : == laisse fuiter des informations ; utilisez la comparaison en temps constant.