以前Slackのコマンドを作成する記事を投稿しましたが、Slackからのリクエストを受け取った際に正当なものかを検証する機能があるようなので、実装を試してみます。
実装方法は2種類あるようですが、Verification Tokenを使用する方法は現在は非推奨になっているようなので、今回はSigning Secretを使った方法になります。
実装前の準備
まずはアプリの設定画面でSigning Secretを取得しておきます。
ダッシュボードの左メニューからSettings > Basic Informationを選択します。

App CredentialsのSigning Secretを表示してコピペしておきます。

実装方法
検証の大まかな流れは以下のようになります。
- リクエストヘッダーのX-Slack-Request-TimestampとX-Slack-Signature、リクエストボディを取得
- バージョン番号(v0)、タイムスタンプ(X-Slack-Request-Timestamp)、リクエストボディを「:」で連結
- 先ほど取得したSigning SecretとHMAC SHA256を使って、2の連結した文字列をハッシュ化
- 3の値とX-Slack-Signatureの値を比較
前回実装した処理の前に検証の処理を追加してみます。
// 検証に使用する項目の取得
$secret_key = 'Signing Secretの値をここに入れる';
$ts = (int) $_SERVER["HTTP_X_SLACK_REQUEST_TIMESTAMP"];
$body = file_get_contents('php://input');
$signature = $_SERVER["HTTP_X_SLACK_SIGNATURE"];
// 一定時間(5分)以上経過していないか確認
if(time() - $ts > 60 * 5) {
echo '5分以上経過しています。';
return false;
}
// バージョン番号とタイムスタンプとリクエストボディを連結
$hash_data = "v0:${ts}:${body}";
// ハッシュ化
$hash = 'v0=' . hash_hmac('sha256', $hash_data, $secret_key);
// 比較して一致しない場合は認証エラー
if($hash !== $signature) {
echo '認証に失敗しました。';
return false;
}
$channel_name = $_POST["channel_name"];
$user_name = $_POST["user_name"];
$message = $_POST["text"];
echo "${channel_name}で${user_name}さんが${message}と送信しました。";
大まかな流れはコメントに書いた通りですが、認証に失敗した場合は「認証に失敗しました。」というメッセージが送信されるようになっています。
コメントが承認されるまで時間がかかります。