Vérification de signature
Chaque requête webhook inclut un header de signature que vous devez vérifier pour vous assurer que la requête provient bien d’Ikawaari.
Fonctionnement
Chaque endpoint webhook possède un secret de signature unique (commence par whsec_). Ikawaari utilise ce secret pour générer une signature HMAC-SHA256 incluse dans le header Ikawaari-Signature.
Le secret est affiché une seule fois à la création ou après une rotation. Si vous ne l’avez plus, faites tourner le secret et mettez à jour votre backend marchand. Ce secret est différent de votre clé API Ikawaari.
La vérification doit utiliser le corps brut exact reçu par votre serveur. Ne parsez pas puis ne re-sérialisez pas le JSON avant de calculer la signature: les espaces, l’ordre ou l’encodage peuvent changer et provoquer un rejet valide.
Étapes de vérification
1. Extraire la signature
Ikawaari-Signature: t=1708300800,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
2. Préparer le payload signé
{timestamp}.{raw_body}
3. Calculer la signature attendue
- Node.js
- Python
import Ikawaari from '@ikawaari/sdk';
const client = new Ikawaari({ apiKey: process.env.IKAWAARI_API_KEY });
const event = client.webhooks.constructEvent(
rawBody,
request.headers['ikawaari-signature'],
process.env.IKAWAARI_WEBHOOK_SECRET
);
Avec Express, exposez le corps brut sur cette route:
app.post('/webhooks/ikawaari', express.raw({ type: 'application/json' }), (req, res) => {
const event = client.webhooks.constructEvent(
req.body.toString('utf8'),
req.headers['ikawaari-signature'],
process.env.IKAWAARI_WEBHOOK_SECRET
);
res.sendStatus(200);
});
Sans SDK:
const crypto = require('crypto');
function verifyWebhookSignature(payload, header, secret) {
const [tPart, vPart] = header.split(',');
const timestamp = tPart.split('=')[1];
const signature = vPart.split('=')[1];
const signedPayload = `${timestamp}.${payload}`;
const expected = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
// Comparaison sûre vis-à-vis du timing
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
import hmac
import hashlib
def verify_webhook_signature(payload: str, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
timestamp = parts["t"]
signature = parts["v1"]
signed_payload = f"{timestamp}.{payload}"
expected = hmac.new(
secret.encode(), signed_payload.encode(), hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
4. Rejeter les événements trop anciens
Vérifiez que l’horodatage se trouve dans une fenêtre de 5 minutes par rapport à l’heure courante afin de prévenir les attaques par rejeu.
Vérifiez toujours les signatures webhook en production. Ne faites jamais confiance à un payload webhook sans vérification.