同じJSONなのに、
署名が合わない。
raw bodyで比べる。

結論:送信元が本文へHMAC署名を付ける場合、n8nで解析し直したJSONではなく、受信した本文そのものからHMACを計算する。公開テンプレでは、正しい要求だけ200、改変・期限切れ・署名不備は同じ401で止める。

このページが合う人:n8nのWebhookでHMAC-SHA256署名を確認したい人、JSONは同じに見えるのに署名不一致になる人。

分かること:raw bodyを使う理由、Crypto認証情報の置き場所、拒否すべき入力、確認済みテンプレの使い方。

先に用意するもの:送信元の公式仕様にある署名対象、署名ヘッダー名、出力形式、timestamp規則。試験には本番値ではなく、試験用secretと合成JSONを使う。

次の行動:下の4項目を送信元仕様と照合する。本文だけをHMAC-SHA256で署名する形式なら、公開テンプレを非公開のまま取り込んで試す。

似た実装を先に見る:このHMACガードを含む公開テンプレが、awesome-n8n-templatesのPR #189として2026年8月15日にmainへマージされた。顧客案件の実績や本番保証ではなく、合成データで確認した公開テンプレ。

最初に、送信元仕様の4項目を見る

「HMAC-SHA256を使う」だけでは設定を決められない。送信元の公式ドキュメントで、次の4項目がすべて一致するか確認する。

確認するもの公開テンプレの前提違う場合
署名対象受信した本文全体timestamp・method・path・一部headerを含むなら計算式を変更
headerX-Automation-Signature送信元指定の名前へ変更
形式sha256= + 64桁hexBase64や別接頭辞なら形式と比較処理を変更
時刻署名済み本文のsent_atheader内のtimestampを署名する形式なら取り出し方を変更

4項目のどれかが不明なら、推測して本番へ出さない。送信元が提供する署名生成例と試験用payloadを先に使う。

同じJSONでも、送った文字列が違えば署名は変わる

次の2つはJSONとして読むと同じ内容。しかし、空白と改行を含む実際のバイト列は異なる。上を署名して下を送れば、正しく拒否される。

{"event_id":"evt_example-0001","sent_at":1786723200,"payload":{"action":"example"}}

{
  "event_id": "evt_example-0001",
  "sent_at": 1786723200,
  "payload": { "action": "example" }
}

WebhookノードでRaw Bodyを有効にすると、受信本文をbinary propertyのdataとして後続へ渡せる。Cryptoノードはこのbinary dataへHMACを計算する。解析後の$json.bodyを文字列化し直さない。

業務処理より前に、4段階で止める

  • 01 / RECEIVE

    raw bodyを受信

    WebhookでRaw Bodyを有効化。本文とheaderを受け取る。

  • 02 / COMPUTE

    HMACを計算

    Crypto認証情報のsecretで、binary dataへSHA256を適用。

  • 03 / CHECK

    署名と時刻を確認

    形式、digest、signed timestamp、event_id、Content-Typeを確認。

  • 04 / RESPOND

    200か401へ分岐

    条件を満たす場合だけ受理。詳細を返さず同じ401で拒否。

公開ワークフローのCryptoノードにはsecretを含めていない。取り込み後、利用者自身のn8nでCrypto認証情報を作り、Compute Body HMACへ割り当てる。

n8n 2.33.7で確認した6ケース

外部サービスへ接続しない環境で、実在データを含まない要求だけを送った。確認したのは次のHTTP結果。顧客案件の実績や本番環境の安全性を示すものではない。

送った条件結果確認した意味
空白を含む本文 + その本文の正しい署名200 受理raw bodyから計算できる
空白を含む本文 + compact JSON側の署名401 拒否JSONの再文字列化を使っていない
本文を1項目改変401 拒否改変を受理しない
正しく署名した期限切れ本文401 拒否5分より古い要求を受理しない
署名headerなし401 拒否未署名を受理しない
署名形式が不正401 拒否想定外の形式を受理しない

公開テンプレを試す手順

  1. ワークフローJSONを取り込み、公開しない状態を保つ。
  2. n8nのCrypto認証情報を作り、試験用HMAC secretを入れる。
  3. Compute Body HMACへ認証情報を割り当てる。
  4. 送信元仕様とheader名、署名対象、hex形式、timestamp規則を比べる。
  5. 合成JSONで、正しい署名と改変した本文を1回ずつ送る。
  6. 拒否側が後続処理へつながっていないことを確認してから、業務ノードを追加する。

まだn8n環境がない場合は、n8n Cloudとセルフホストの責任範囲を先に確認する。署名を試すためだけにVPSを契約せず、更新・バックアップ・復旧を誰が担当するかで選ぶ。

このテンプレをそのまま使えない条件

  • 送信元が本文以外にtimestamp、method、path、headerを連結して署名する。
  • digestがBase64、複数署名、鍵ID付き、公開鍵署名など別形式。
  • 送信元専用のn8n Triggerノードが、すでに署名確認を内蔵している。
  • 同じeventを5分以内に再送された場合も、必ず1回だけ処理する必要がある。

5分の時刻窓は古い要求を止めるが、窓の内側の重複は止めない。厳密な二重処理防止には、署名済みのevent IDを永続保存し、処理前に使用済みか確認する。

本番前に追加で確認するものは、鍵の切替、時計ずれ、送信元の再試行、同一eventの重複、本文サイズ、レート制限。今回の確認には本番負荷試験と各社Webhookとの接続を含めていない。

よくある質問

JSONの内容が同じでもHMAC署名が一致しないことはある?

ある。空白、改行、キー順などが変わると送信バイト列が変わる。送信元が署名した本文そのものを使って計算する。

5分以内のtimestampなら同じWebhookを何度送っても安全?

安全とは限らない。時刻の確認は古い要求を拒否するもの。同じ時間内の重複には、event IDなどを保存して二重処理を止める仕組みが別に必要。

StripeやGitHubへそのまま使える?

そのまま使えるとは限らない。送信元ごとに署名対象と形式が違う。専用Triggerノードが署名確認を内蔵している場合もあるため、送信元とn8nの現行公式仕様を先に確認する。

公式情報

広告・確認範囲

本ページに第三者アフィリエイト広告なし。自社の有料構築サービス案内を含む。AUTOMATION NOTEはn8n公式・認定パートナーではない。

確認日:2026-08-15 / n8n 2.33.7 / 合成データ6ケース / 外部サービス接続なし / 本番負荷・各社互換性は未確認