X-ThunderPhone-Signature. Configurez la vérification correctement une seule fois et
réutilisez le même utilitaire dans chaque gestionnaire.
L’algorithme
- Lisez le corps de requête brut — les octets exacts que nous vous avons envoyés par POST.
- Calculez
hmac_sha256(secret, body).hexdigest(). - Comparez en temps constant avec
X-ThunderPhone-Signature. (Une comparaison naïve de chaînes expose des informations de temporisation.)
, et : sans espaces), UTF-8. Cela vous offre une deuxième méthode, entièrement
équivalente, lorsque votre framework n’expose que le JSON analysé :
resérialisez de manière canonique et calculez le HMAC de ce résultat.
Quel secret ?
Stockez le secret dans votre gestionnaire de secrets ou une variable d’environnement — ne le validez jamais dans votre dépôt.
Implémentations de référence
Les quatre vérifient le corps de requête brut :Configuration spécifique au framework
Vérifier les appels d’outils
Lorsque l’agent invoque directement l’un de vos outils de fonction (l’outil possède unendpoint), la requête inclut deux en-têtes ThunderPhone en plus de
vos endpoint.headers configurés :
X-ThunderPhone-Call-ID— l’identifiant numérique de l’appel en cours.X-ThunderPhone-Signature— HMAC-SHA256, utilisant comme clé votre secret de webhook au niveau de l’organisation, sur les octets exacts du corps de la requête.
verify() fonctionne sans modification, avec deux particularités :
- Les outils
GET/DELETEn’ont pas de corps. Les arguments sont transmis en tant que paramètres de requête, et la signature est calculée sur la chaîne d’octets vide — doncverify(b"", sig, secret)(Python) ouverify(Buffer.alloc(0), sig, secret)(Node). Ne hachez pas la chaîne de requête. - Les organisations sans webhook hérité configuré n’ont pas de secret d’organisation.
Dans ce cas, les appels d’outils incluent uniquement
X-ThunderPhone-Call-IDet aucun en-tête de signature. Configurez le webhook hérité (PUT /v1/webhook) pour obtenir un secret de signature, ou authentifiez les appels d’outils avec votre propre en-tête viaendpoint.headers.
endpoint, transmis
à votre webhook d’organisation sous la forme telephony.tool / web.tool) est un
webhook signé classique — la procédure standard ci-dessus s’applique. Consultez
Outils de fonction pour les deux formats de requête.
Pièges courants
Resérialisation avec le formatage par défaut
Resérialisation avec le formatage par défaut
Analyser le corps puis le réexporter avec les paramètres par défaut de votre bibliothèque JSON
(espaces après
, / :, clés dans l’ordre d’insertion) produit
des octets différents et invalide le HMAC. Vérifiez le corps brut — ou, si
vous devez le resérialiser, reproduisez exactement notre forme canonique : clés
triées, séparateurs compacts, UTF-8.Le framework analyse automatiquement le JSON
Le framework analyse automatiquement le JSON
Le middleware
express.json() d’Express consomme le flux du corps
et vous perdez les octets bruts. Utilisez express.raw() spécifiquement sur la route
du webhook, ou mettez en mémoire tampon le corps brut dans un pré-middleware.
Même principe pour NestJS / Koa — consultez leur documentation sur le « corps brut ».Comparaison non sûre vis-à-vis du timing
Comparaison non sûre vis-à-vis du timing
expected === signature en JS ou expected == signature en
Python sont des comparaisons dont la durée varie. Utilisez crypto.timingSafeEqual
ou hmac.compare_digest, respectivement. La différence de performances
est nulle.Mauvais secret pour les points de terminaison d’outils
Mauvais secret pour les points de terminaison d’outils
Les appels directs aux points de terminaison d’outils sont signés avec le secret de webhook
au niveau de l’organisation (
GET /v1/webhook) — et non avec un secret propre à chaque point de terminaison
provenant de /v1/developer/webhook-endpoints. Réutilisez la même fonction verify(),
mais assurez-vous de lui fournir le secret de l’organisation sur les routes d’outils.Hachage de la chaîne de requête sur les outils GET/DELETE
Hachage de la chaîne de requête sur les outils GET/DELETE
Pour les méthodes d’outils sans corps, la signature couvre la chaîne d’octets
vide, ce qui conserve une recette universelle : appliquez le HMAC au corps brut de la requête,
quel qu’il soit. Le hachage de l’URL ou de la chaîne de requête ne correspondra jamais.
Ne pas renvoyer 401 en cas de non-correspondance
Ne pas renvoyer 401 en cas de non-correspondance
Renvoyer 200 lorsqu’une vérification échoue fait du gestionnaire une cible de rejeu.
Répondez toujours avec un statut autre que 2xx si la vérification échoue.
Étapes suivantes
Vue d’ensemble des webhooks
Sémantique de livraison, tentatives, adresses IP source.
Points de terminaison des webhooks
Gérez plusieurs URL, faites tourner les secrets.
Outils de fonction
Les deux modes d’invocation d’outils et les formats de leurs requêtes.
Intégrations d’outils
Créez une intégration complète basée sur des outils, de bout en bout.