Skip to main content
Кожен запит, який ми надсилаємо на ваш сервер — доставки вебхуків і виклики кінцевих точок інструментів — містить підпис HMAC-SHA256 у заголовку X-ThunderPhone-Signature. Один раз правильно налаштуйте перевірку та підключіть той самий допоміжний засіб до кожного обробника.

Алгоритм

  1. Прочитайте необроблене тіло запиту — точні байти, які ми надіслали вам методом POST.
  2. Обчисліть hmac_sha256(secret, body).hexdigest().
  3. Порівняйте в сталий час зі значенням X-ThunderPhone-Signature. (Наївне порівняння рядків розкриває інформацію про час виконання.)
Ми підписуємо саме ті байти, які передаємо, тому перевірка необробленого тіла завжди працює. Ці байти також є канонічною JSON-серіалізацією корисного навантаження — ключі відсортовано за алфавітом, компактні роздільники (, і : без пробілів), UTF-8. Це дає вам другий, цілком еквівалентний спосіб, якщо ваш фреймворк надає лише розібраний JSON: повторно серіалізуйте його канонічно та обчисліть HMAC.
Надавайте перевагу необробленому тілу — це на один крок менше та не залежить від особливостей повторного перетворення чисел JSON у деяких мовах.

Який секрет?

Зберігайте секрет у менеджері секретів або змінній середовища — ніколи не додавайте його до комітів.

Довідкові реалізації

Усі чотири перевіряють необроблене тіло запиту:

Налаштування для конкретних фреймворків

Перевірка викликів інструментів

Коли агент безпосередньо викликає один із ваших функціональних інструментів (інструмент має endpoint), запит містить два заголовки ThunderPhone разом із налаштованими вами endpoint.headers:
  • X-ThunderPhone-Call-ID — числовий ідентифікатор активного дзвінка.
  • X-ThunderPhone-Signature — HMAC-SHA256 із ключем у вигляді вашого секрету webhook на рівні організації, обчислений для точних байтів тіла запиту.
Той самий допоміжний метод verify() працює без змін, але є два нюанси:
  1. Інструменти GET / DELETE не мають тіла. Аргументи передаються як параметри запиту, а підпис обчислюється для порожнього рядка байтів — тобто verify(b"", sig, secret) (Python) або verify(Buffer.alloc(0), sig, secret) (Node). Не хешуйте рядок запиту.
  2. Організації без налаштованого застарілого webhook не мають секрету організації. У такому разі виклики інструментів містять лише X-ThunderPhone-Call-ID і не мають заголовка підпису. Налаштуйте застарілий webhook (PUT /v1/webhook), щоб отримати секрет для підписування, або автентифікуйте виклики інструментів власним заголовком через endpoint.headers.
Диспетчеризація інструментів у режимі webhook (інструменти без endpoint, що доставляються до webhook вашої організації як telephony.tool / web.tool) є звичайним підписаним webhook — застосовуйте стандартний підхід вище. Див. розділ Функціональні інструменти для обох форматів запитів.

Поширені помилки

Аналіз тіла запиту та повторне виведення за допомогою стандартних налаштувань вашої JSON-бібліотеки (пробіли після , / :, ключі в порядку вставлення) створює інші байти та порушує HMAC. Перевіряйте необроблене тіло запиту — або, якщо потрібно повторно серіалізувати його, точно дотримуйтеся нашої канонічної форми: відсортовані ключі, компактні роздільники, UTF-8.
Проміжне ПЗ Express express.json() споживає потік тіла запиту, і ви втрачаєте необроблені байти. Використовуйте express.raw() безпосередньо для маршруту вебхука або буферизуйте необроблене тіло в попередньому проміжному ПЗ. Те саме стосується NestJS / Koa — перегляньте їхню документацію щодо «raw body».
expected === signature у JS або expected == signature у Python — це порівняння зі змінним часом виконання. Використовуйте crypto.timingSafeEqual або hmac.compare_digest відповідно. Різниця в продуктивності відсутня.
Прямі виклики кінцевих точок інструментів підписуються за допомогою секрету вебхука на рівні організації (GET /v1/webhook) — а не секрету для кожної кінцевої точки з /v1/developer/webhook-endpoints. Повторно використовуйте ту саму функцію verify(), але переконайтеся, що передаєте їй секрет організації в маршрутах інструментів.
Для методів інструментів без тіла запиту підпис охоплює порожній рядок байтів, зберігаючи один універсальний підхід: обчислюйте HMAC для необробленого тіла запиту, яким би воно не було. Хеш URL або рядка запиту ніколи не збігатиметься.
Повернення 200 у разі невдалої перевірки робить обробник ціллю для повторного відтворення запитів. Завжди повертайте статус не з діапазону 2xx, якщо перевірка не пройшла.

Наступні кроки

Огляд вебхуків

Семантика доставки, повторні спроби, IP-адреси джерел.

Кінцеві точки вебхуків

Керуйте кількома URL-адресами, змінюйте секрети.

Function Tools

Два шляхи виклику інструментів і формати їхніх запитів.

Інтеграції інструментів

Створіть повну інтеграцію на основі інструментів від початку до кінця.