X-ThunderPhone-Signature. Implementa la verificación correctamente una vez y reutiliza el mismo helper en cada controlador.
El algoritmo
- Lee el cuerpo sin procesar de la solicitud: los bytes exactos que te enviamos mediante POST.
- Calcula
hmac_sha256(secret, body).hexdigest(). - Compara en tiempo constante con
X-ThunderPhone-Signature. (Una comparación de cadenas ingenua filtra información de temporización).
, y : sin espacios), UTF-8. Esto te ofrece una segunda receta totalmente
equivalente cuando tu framework solo expone JSON analizado:
vuelve a serializar canónicamente y calcula el HMAC de eso.
¿Qué secreto?
Almacena el secreto en tu administrador de secretos o variable de entorno; nunca lo confirmes en el repositorio.
Implementaciones de referencia
Las cuatro verifican el cuerpo sin procesar de la solicitud:Integración específica del framework
Verificación de llamadas a herramientas
Cuando el agente invoca directamente una de tus herramientas de función (la herramienta tiene unendpoint), la solicitud incluye dos encabezados de ThunderPhone junto
con tus endpoint.headers configurados:
X-ThunderPhone-Call-ID— el ID numérico de la llamada activa.X-ThunderPhone-Signature— HMAC-SHA256, con clave de tu secreto de webhook a nivel de organización, sobre los bytes exactos del cuerpo de la solicitud.
verify() funciona sin cambios, con dos particularidades:
- Las herramientas
GET/DELETEno tienen cuerpo. Los argumentos se envían como parámetros de consulta y la firma se calcula sobre la cadena de bytes vacía; es decir,verify(b"", sig, secret)(Python) overify(Buffer.alloc(0), sig, secret)(Node). No calcules el hash de la cadena de consulta. - Las organizaciones sin un webhook heredado configurado no tienen secreto de organización. En
ese caso, las llamadas a herramientas incluyen solo
X-ThunderPhone-Call-IDy ningún encabezado de firma. Configura el webhook heredado (PUT /v1/webhook) para obtener un secreto de firma, o autentica las llamadas a herramientas con tu propio encabezado medianteendpoint.headers.
endpoint, enviadas
a tu webhook de organización como telephony.tool / web.tool) es un webhook
firmado común: se aplica la receta estándar anterior. Consulta
Herramientas de función para ambas formas de solicitud.
Errores comunes
Reserializar con el formato predeterminado
Reserializar con el formato predeterminado
Analizar el cuerpo y volver a serializarlo con los valores
predeterminados de tu biblioteca JSON (espacios después de
, / :, claves en orden de inserción) produce
bytes diferentes y rompe el HMAC. Verifica el cuerpo sin procesar; o, si
debes reserializarlo, coincide exactamente con nuestra forma canónica: claves
ordenadas, separadores compactos, UTF-8.El framework analiza JSON automáticamente
El framework analiza JSON automáticamente
El middleware
express.json() de Express consume el flujo del cuerpo
y pierdes los bytes sin procesar. Usa express.raw() específicamente en la ruta
del webhook, o almacena el cuerpo sin procesar en un middleware previo.
Lo mismo ocurre con NestJS / Koa: consulta su documentación sobre “raw body”.Comparación no segura frente a ataques de temporización
Comparación no segura frente a ataques de temporización
expected === signature en JS o expected == signature en
Python son comparaciones con tiempo variable. Usa crypto.timingSafeEqual
o hmac.compare_digest, respectivamente. La diferencia de rendimiento
es nula.Secreto incorrecto para endpoints de herramientas
Secreto incorrecto para endpoints de herramientas
Las llamadas directas a endpoints de herramientas se firman con el secreto
de webhook a nivel de organización (
GET /v1/webhook), no con ningún secreto por endpoint
de /v1/developer/webhook-endpoints. Reutiliza la misma función verify(),
pero asegúrate de proporcionarle el secreto de la organización en las rutas de herramientas.Hashear la cadena de consulta en herramientas GET/DELETE
Hashear la cadena de consulta en herramientas GET/DELETE
Para los métodos de herramientas sin cuerpo, la firma cubre la cadena de bytes
vacía, manteniendo una única receta universal: aplica HMAC al cuerpo sin procesar de la solicitud,
sea cual sea. Hashear la URL o la cadena de consulta nunca coincidirá.
No devolver 401 cuando no coincide
No devolver 401 cuando no coincide
Devolver 200 cuando falla la verificación convierte el controlador en un objetivo
de repetición. Responde siempre con un código distinto de 2xx si la verificación falla.
Próximos pasos
Descripción general de webhooks
Semántica de entrega, reintentos e IP de origen.
Endpoints de webhook
Administra varias URL y rota secretos.
Herramientas de función
Las dos rutas de invocación de herramientas y las formas de sus solicitudes.
Integraciones de herramientas
Crea una integración completa respaldada por herramientas de principio a fin.