Quand un webhook a un secret, chaque requête est signée avec HMAC-SHA256 sur l’en-tête d’horodatage et le corps brut.
X-Mateflow-Signature = "sha256=" + hex(
HMAC-SHA256(secret, X-Mateflow-Timestamp + "." + raw_request_body)
)
- Utilisez les octets bruts. Les caractères spéciaux en HTML peuvent être échappés dans le corps ; analyser le JSON puis le resérialiser produit donc d’autres octets, et la signature ne correspondra pas.
- Prenez l’horodatage dans l’en-tête, pas dans le corps. Un renvoi manuel ne met à jour que l’horodatage de l’en-tête et la signature.
- Une vérification de l’horodatage n’interfère pas avec les nouvelles tentatives. Chaque nouvelle tentative automatique et chaque renvoi manuel est signé à nouveau : une fenêtre de 5 minutes suffit.
const crypto = require('crypto');
// rawBody must be the untouched bytes, e.g. from express.raw({ type: 'application/json' }).
function verifyMateflowSignature(rawBody, headers, secret, toleranceSeconds = 300) {
const timestamp = headers['x-mateflow-timestamp'];
const received = headers['x-mateflow-signature'] || '';
if (!timestamp || Math.abs(Date.now() / 1000 - Number(timestamp)) > toleranceSeconds) {
return false;
}
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(`${timestamp}.`)
.update(rawBody)
.digest('hex');
const a = Buffer.from(received);
const b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}import hashlib
import hmac
import time
def verify_mateflow_signature(raw_body: bytes, headers, secret: str, tolerance_seconds: int = 300) -> bool:
timestamp = headers.get("X-Mateflow-Timestamp", "")
received = headers.get("X-Mateflow-Signature", "")
if not timestamp.isdigit() or abs(time.time() - int(timestamp)) > tolerance_seconds:
return False
signed = timestamp.encode() + b"." + raw_body
expected = "sha256=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(received.encode(), expected.encode())Vecteur de test
Utilisez ces valeurs pour vérifier votre calcul de signature. L’horodatage a expiré : assouplissez donc votre fenêtre de temps pendant les tests.
secret my_signing_secret
X-Mateflow-Timestamp 1793664000
raw body (UTF-8) {"event":"member.joined","data":{"username":"张三"}}
X-Mateflow-Signature sha256=3f4c83828ce0086150c9bd48c1654899357b7c05265c1d1b6c172225ee04b4b4Changer de secret
Un nouveau secret prend effet dès qu’il est enregistré, et les nouvelles tentatives en attente sont elles aussi signées avec lui. Il n’existe aucune période où Mateflow signe avec les deux ; faites donc accepter à votre récepteur l’ancien et le nouveau secret pendant la transition.