SlackのOAuthフローをDockerを使ってPoCする


経緯

前回 、ChatworkのOAuthフローをDockerで作ってみました。実はSlackに対しても同様の調査をする必要がありましたので、今回はその環境を使ってSlackのOAuthフローを作っていきたいと思います。使用するSlack APIのバージョンはv2です。

準備

Slack app directory から Appの作成

SlackでOAuthを行うためにはまず、Slack Appを作る必要があります。
テスト用に作成したWorkspaceにAppを作っていきます。

まだ1つもAppが存在しない場合はこのような表示になっていますので、Create an Appをクリックしましょう。

Appの名称を入力して、作成先のWorkspaceを選択します。
ここで入力した名称は第三者の目に触れる場所に表示されるので、正式な名称を入力ましょう。今回はPoCなので適当に名前をつけました。

Appが作成されるとOAuth認証に必要なClient IDClient Secretが発行されます。

OAuth認証の設定

Appが作成されたらAppにOAuth認証の設定を施します。
左のメニューから OAuth & Permissions をクリックします。

いくつかある設定項目の中の Redirect URLs に OAuth認証に使用するリダイレクトURLを設定します。/oauthは既にChatwork検証時に使用してしまったので、 https://localhost:3443/oauth_slack というURLにしました。

OAuth認証後にメッセージのテスト送信を行うので、Bot用のScopes(権限)に chat:write を追加します。
Slack API v1では認証URLにScopeを指定すればOKでしたが、v2ではこちらにも権限を設定しないと認証URLにアクセスした際にエラーになりました。

WorkspaceのチャンネルにAppをインストールする

指定したチャンネルIDにメッセージを送信するには、チャンネルにAppがインストールされている必要があります。この手続を行わないと、API実行時に not_in_channel というエラーが発生します。

インテグレーションタブを選択して「アプリを追加する」をクリックします。

先ほど作成した MyTest がリストアップされていますので、「追加」をクリック。

これでチャンネル #generalMyTest がメッセージを送信できるようになりました。

Express.jsにRouterを追加する

Express.jsの環境構築については前回の記事を参照してください。
前回構築したExpress.jsにSlack OAuth認証用のRouterを新しく追加します。

OAuthリダイレクト用のRouterを追加

今回は /oauth_slack というパスを用意することにしました。

src/app.js

...
var usersRouter = require('./routes/users');
var oauthRouter = require('./routes/oauth');
var oauthSlackRouter = require('./routes/oauthSlack'); // <- 追加
...
app.use('/users', usersRouter);
app.use('/oauth', oauthRouter);
app.use('/oauth_slack', oauthSlackRouter); // <- 追加

なお、今回はAccess Tokenの取得やメッセージの送信にSlackから提供されている @slack/web-api を使用します。パッケージの使い方はこちらのドキュメントを参照してください。

src/routes/oauthSlack.js

const express = require('express');
const router = express.Router();
const { WebClient } = require('@slack/web-api');

router.get('/', async function (req, res, next) {
  let isSuccess = false;

  try {
    const wc = new WebClient();
    /**
     * Access Tokenを取得する
     */
    const resultToken = await wc.oauth.v2.access({
      client_id: process.env.SLACK_CLIENT_ID,
      client_secret: process.env.SLACK_CLIENT_SECRET,
      code: req.query.code,
    });
    console.log(resultToken);

    /**
     * テストメッセージを送信する
     */
    const resultMessage = await wc.chat.postMessage({
      token: resultToken.access_token,
      channel: process.env.SLACK_TEST_CHANNEL_ID,
      text: 'Hello!',
    });
    console.log(resultMessage);

    isSuccess = true;
  } catch (error) {
    console.error(error);
    isSuccess = false;
  }

  res.render('oauth', {
    isSuccess,
  });
});

module.exports = router;

環境変数の定義

Express.jsで使用するSlack OAuth用の環境変数を定義します。チャンネルIDはブラウザのURLから取得できます。

app.env

...

# Slack Client ID
SLACK_CLIENT_ID=[App作成で生成したClient ID]
# Slack Client Secret
SLACK_CLIENT_SECRET=[App作成で生成したClient Secret]
# Slack メッセージのテスト送信に使用するChannel ID
SLACK_TEST_CHANNEL_ID=[AppをインストールしたチャンネルID]

動かしてみる

前回と同様に docker-compose コマンドで起動します

$ docker-compose up

下記のURLからOAuth認証フローを開始します。v1とはURLが異なるので注意してください。

https://slack.com/oauth/v2/authorize?client_id={client_id}&scope=chat:write&user_scope=

無事に認証画面が表示されました。「許可する」ボタンをクリックしてみましょう。

ブラウザに Success!! と表示されていればメッセージの送信まで成功しています。Slackの #general チャンネルを確認してみましょう。

#general チャンネルにメッセージが送信されていることが確認できました。

まとめ

Slack API v2 を使ったOAuth認証とメッセージの送信について書かれた記事がまだ少なかったので、Slack Appを作成する際にみなさまの参考になれば幸いです。