<b>HMAC-подпись на входящем хуке — это фильтр, а не опция</b>
Смотрим в тело запроса: сначала берём raw body, потом считаем HMAC на стороне приёмника, и только затем сравниваем с заголовком. Если хендлер парсит JSON до проверки — вы уже проиграли: пробелы, порядок полей и нормализация строк ломают совпадение, а атакующий получает лишний шанс подсунуть мусор.
Базовый набор без магии:
— общий секрет хранить как секрет, не в коде и не в логе;
— использовать compare_digest/constant-time compare, иначе словите утечки по времени;
— проверять timestamp или nonce, чтобы не принимать старый пакет второй раз;
— отклонять запросы без подписи и без понятной схемы алгоритма.
Типичная ошибка — подписывать уже распарсенный объект. Подписывают байты, а не красивую структуру после round-trip через сериализатор. Если провайдер шлёт <code>raw_body</code>, его и кладите в HMAC. Если шлёт base64 или hex — фиксируйте формат явно, без “ну мы там как-нибудь договоримся”.
Идемпотентность — это не роскошь, а база: даже валидная подпись не спасает от дубля из ретрая. Храните fingerprint события, <tg-spoiler>event_id + timestamp + signature</tg-spoiler>, и отвечайте 2xx только после записи в очередь или БД. Иначе внешний сервис решит, что у вас всё ок, а вы потеряете событие.
Если подпись не сошлась — 401/403, без подробного объяснения. Логируйте только метаданные: длину тела, имя заголовка, причину отказа. Содержимое полезной нагрузки не светим. Ретрай-политика решает всё, но только когда вы проверяете её до того, как пустили запрос в бизнес-логику.
Автоматизация на вебхуках
@webhook_automation_hub_arb
<b>HMAC-подпись на входящем хуке — это фильтр, а не опция</b>
Этот пост опубликован в Telegram-канале Автоматизация на вебхуках. Подписаться можно по ссылке: @webhook_automation_hub_arb.