SIGNATURE
Vérifiez que la notification vient bien de Cord.
Chaque envoi porte X-Cord-Signature-V1, avec un horodatage et le HMAC-SHA256 du corps brut, signé avec le secret de votre endpoint. Vous le validez en quelques lignes avant de traiter l’événement, et l’horodatage vous protège contre le renvoi d’un ancien envoi par un tiers.
- X-Cord-Event-Id pour dédupliquer sans lire le corps
- X-Cord-Attempt indique le numéro de la tentative d’envoi
- Pendant une rotation, la signature utilise le nouveau secret et l’ancien
import crypto from 'node:crypto';
// header = req.headers['x-cord-signature-v1'], rawBody = corps brut, non analysé
export function verifyCord(rawBody, header, secret) {
const parts = header.split(',');
const t = parts.find((p) => p.startsWith('t='))?.slice(2);
if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const expected = crypto.createHmac('sha256', secret)
.update(`${t}.${rawBody}`).digest();
// pendant une rotation, deux v1 arrivent : une seule correspondance suffit
return parts.filter((p) => p.startsWith('v1=')).some((p) => {
const got = Buffer.from(p.slice(3), 'hex');
return got.length === expected.length && crypto.timingSafeEqual(got, expected);
});
}