0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Chatworkシリーズ #24】ChatworkのWebhookをn8nで受けるなら、HMAC署名検証は必ずやれ

0
Last updated at Posted at 2026-03-31

そのWebhook、誰からのリクエストか確認してる?

n8nでChatworkのWebhookを受けて、メッセージに自動応答するBotを動かしている人は増えてきた。Webhook nodeのURLを設定して、Chatwork管理画面に貼って、動いた。やった。

で、そこで終わっていないか。

そのURLに、Chatwork以外の誰かがPOSTしたらどうなるか。答えはシンプルで、Botが普通に反応する。偽のメッセージを送りつければ、Botはそれを本物だと思って処理する。

Chatworkの署名検証の仕組み

ChatworkはWebhookリクエストのヘッダに X-ChatWorkWebhookSignature という署名を付けてくる。HMAC-SHA256で計算されている。

Base64( HMAC-SHA256( Base64decode(token), request_body ) )
  • token: Chatwork管理画面のWebhook設定画面で表示されるBase64エンコード済みの文字列
  • request_body: リクエストのボディ(JSON文字列そのもの)

受け取り側で同じ計算をして、ヘッダの署名と一致するか確かめる。一致しなければ捨てる。GitHubのWebhookやSlackのSigning Secretと同じ方式。

n8nのCode nodeに貼るだけのコード

const crypto = require('crypto');

const WEBHOOK_TOKEN = 'YOUR_WEBHOOK_TOKEN';

const headers = $input.first().json.headers;
const signature = headers['x-chatworkwebhooksignature']
  || headers['X-ChatWorkWebhookSignature']
  || '';

const body = $input.first().json.body;
const bodyStr = typeof body === 'string' ? body : JSON.stringify(body);

const expected = crypto
  .createHmac('sha256', Buffer.from(WEBHOOK_TOKEN, 'base64'))
  .update(bodyStr)
  .digest('base64');

if (signature !== expected) {
  return []; // 署名不一致 → 空配列でワークフロー停止
}

return [{
  json: {
    verified: true,
    ...($input.first().json)
  }
}];

ポイント3つ

1. トークンはBase64デコードしてからHMACの鍵にする。 Buffer.from(WEBHOOK_TOKEN, 'base64') がそれ。ここを忘れると永遠に署名が一致しない。

2. ヘッダ名の大文字・小文字を両方拾う。 n8nのバージョンやプロキシの設定で正規化されることがある。

3. 署名不一致は return [] で静かに無視。 攻撃者にエラーメッセージを返す必要はない。

Webhook nodeの設定

  • Response Mode: 「Immediately」推奨。署名検証で落としたリクエストにタイムアウトまで待たせない
  • Include Headers and Query: 有効にする。デフォルトではヘッダーが後続ノードに渡らないことがある

Kubellの技術者が6言語分の実装を公開している

Chatworkを開発しているKubell社の技術者が、公式に6言語(Ruby, PHP, Python, Go, Java, C#)の実装コードを公開している。開発元がここまで用意しているのに、利用者側が無視するのはもったいない。

「URLが漏れなければ大丈夫じゃない?」

「漏れない保証」はどこにもない。n8nのダッシュボードのスクショをSlackに貼った、URLを含むログが残った。漏れるルートはいくらでもある。

署名検証は保険ではない。リクエストの正当性を担保する唯一の手段だ。

トークンはコードに直書きしない

上のコード例では 'YOUR_WEBHOOK_TOKEN' をそのまま書いているが、本番運用ではn8nのCredential機能やEnvironment Variableに入れる。セキュリティの記事でトークンをハードコードしていたら本末転倒だ。

まとめ

  • ChatworkのWebhookには X-ChatWorkWebhookSignature ヘッダが付いてくる
  • HMAC-SHA256で検証すれば、不正なリクエストを弾ける
  • n8nならCode nodeを1つ追加するだけ。5分で終わる

セキュリティは後回しにしがちだ。でも5分で入れられるなら、入れない理由がない。

Chatworkシリーズ


Chatworkシリーズ

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?