弊社、社内のコミュニケーションツールはSlackなんですが、税理士さん&社労士さんとのやり取りにはChatworkを使っています。
会社共通用のGmailの受信をSlackに通知するようにしたように、Chatworkも一元化できないかなー、と思い調べたら、無料プランでもwebhookを設定できる様子。太っ腹。
サーバー側として今回はGASを使うことにしました。
さて、Chatworkではセキュリティ上、webhookの利用時には署名の検証を推奨しています。
確かにこれがないと全然悪用ができちゃうので仕方がない。
ヘッダーとリクエストパラメーター(非・リクエストボディ)に署名(バイト配列)をBASE64でエンコードした文字列がくっついているので、こちらを検証します。
Chatworkでwebhookを作成するとトークンというBASE64でエンコードされた文字列が発行されるので、
こちらを利用します。
function doPost(e) {
// 別途保存しておいたトークンをbyte[]に
const privateKey = Utilities.base64Decode(PropertiesService.getScriptProperties().getProperty("token"));
// リクエストボディ自体をbyte[]に
const data = Utilities.newBlob(e.postData.contents).getBytes();
// HMAC-sha256で署名(byte[])を作成
const x = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_256, data, privateKey);
// 署名(byte[])をbase64エンコードした文字列とくっついてきた署名文字列を検証
const verifySig = Utilities.base64Encode(x) == e.parameter['chatwork_webhook_signature'];
if (!verifySig) {
// 検証エラー
}
}