Що таке HMAC-підпис і як перевірити вебхук
HMAC — код автентифікації повідомлення на основі хеш-функції і спільного секрету, який доводить, що повідомлення надіслав саме той, хто знає секрет, і його не змінили.
HMAC (Hash-based Message Authentication Code) поєднує повідомлення з секретним ключем і пропускає через хеш-функцію, найчастіше SHA-256. Результат — підпис фіксованої довжини. Отримувач, знаючи той самий секрет, обчислює підпис сам і порівнює з отриманим. Якщо збігається — повідомлення справжнє і не змінене дорогою.
Для вебхуків це критично. URL вашого обробника легко дізнатися чи вгадати, і без перевірки підпису зловмисник може надіслати фальшивий запит «платіж оплачено» та отримати товар безкоштовно. HMAC закриває цю дірку: без секрету правильний підпис не створити.
Деталі, на яких часто помиляються. Підпис рахується від «сирих» байтів тіла запиту — якщо фреймворк уже розпарсив JSON і ви серіалізуєте його назад, порядок полів чи пробіли зміняться, і підпис не зійдеться. Порівнювати підписи треба функцією сталого часу (timingSafeEqual у Node.js, hmac.compare_digest у Python), а не звичайним ==. Якщо сервіс передає мітку часу, перевіряйте, що вона свіжа, щоб захиститися від повторного відтворення старого запиту.
Секрет вебхука зберігайте так само обережно, як API-ключ: не в коді фронтенду, не в публічному репозиторії. Якщо є підозра на витік — згенеруйте новий секрет у кабінеті та оновіть його на сервері.
Moonvex підписує кожен вебхук HMAC і передає підпис у заголовку Moonvex-Signature. Формат і приклад перевірки описані в документації, а Node.js SDK @moonvex/node робить перевірку однією функцією.