トークン・スコープ・OAuth
トークンの分類、最小スコープの原則、そしてこのサイトが OAuth リダイレクトフローを採らない理由
トークンの分類
| トークン | プレフィックス | 表すもの | 主な用途 |
|---|---|---|---|
| bot トークン | xoxb- | アプリ自身の bot ユーザー | ほぼすべての用途。特定のメンバーに紐づかない安定したアイデンティティ |
| user トークン | xoxp- | ワークスペースの特定メンバー | その人が実行したものとして見せる必要がある操作 |
| app-level トークン | xapp- | インストール先のワークスペース横断でのアプリ自身 | Socket Mode(connections:write)などアプリ全体にまたがる操作 |
| workflow トークン | xwfp- | Workflow Builder の 1 ステップ(ごく短時間) | そのステップ内でのデータ読み取り専用。発行から 15 分後、またはステップ終了時のいずれか早いほうで失効する |
分類は Tokens に準拠している。このサイトのパターンは既定で bot トークンを使う。4 つのうち、個人にもワークフローの実行にも Socket Mode にも縛られないのはこれだけだからだ。
workflow トークンと Lists API
xwfp トークンは、ワークフローの起動者からは見えるが bot ユーザーが参加していないチャンネルに対して「借り物の可視性」を持ち込む。Workflow Builder の内側では便利な性質だが、workflow トークンで slackLists.access.set を呼ぶと list_not_found が返り、同じ呼び出しが bot トークンなら通るというコミュニティ報告が少なくとも 1 件ある(slackapi/deno-slack-sdk#472)。これは Slack がドキュメント化した挙動ではなく現場からの報告にすぎないが、リストへの書き込みは workflow トークンではなく bot トークンに寄せておく理由としては十分だ。リスト固有のアクセスモデルについては Lists: アクセスとスコープを参照。
最小スコープ
bot スコープは、実際に機能が使うものだけを要求する。最初から全部盛りにせず、必要になった時点で足していけばよい。スコープは再インストール時に加算される(後述)ので後から増やすコストはなく、逆に使っていないスコープは、ワークスペース管理者がインストール済みアプリを監査したときに説明を求められる権限として残り続ける(Installing with OAuth)。
OAuth リダイレクトなしでインストールする
Slack の OAuth v2 フローは、任意のワークスペースがあなたのアプリをインストールできるようにするための仕組みだ。ユーザーが Slack にリダイレクトされ、要求されたスコープを承認すると、Slack は一時コードを添えて自前サーバーの URL へ返し、サーバーがそのコードをトークンと交換する。しかし、自分のために作ったワークスペース 1 つでしか動かさないアプリには、この一連の手続きはどれも当てはまらない。アプリ自身の OAuth & Permissions ページで Install to Workspace をクリックすること、それ自体がインストールである。Slack はその場でトークンを発行して同じページに表示するので、リダイレクト URL もコード交換もサーバー側のコールバック実装も一切要らない(App distribution)。
OAuth が必要になるとき
リダイレクトフローが効いてくるのは、アプリが自分のワークスペースの外へ出ていく段階だ。public distribution(共有リンクから任意のワークスペースがインストールできる)と org-wide internal distribution(Enterprise Grid 組織内の全ワークスペースにインストールできる)は、どちらもリダイレクトエンドポイントの実装を要求する。自分が動いていないワークスペースのトークンをサーバーへ渡す手段が、Slack にはほかにないからだ。複数ワークスペースへの配布は今回のリリースの対象外で、ここに書いてあることはすべて、既知のワークスペース 1 つを前提としている。
スコープ変更後の再インストール
スコープは加算方式である。新しいスコープを要求してワークスペースにインストールをやり直すと、既存の許可を置き換えるのではなく、そこに追加される。逆に、より小さいマニフェストで入れ直す以外に、トークンのスコープを削る方法はない(Installing with OAuth)。マニフェストやスコープ一覧を編集するだけでは、稼働中のものは何も変わらない -- Slack のマニフェストに関するガイドも、マニフェストの更新はワークスペースへすでに発行済みのトークンを変更しないと述べている(App distribution)。つまり新しく追加したスコープは、ワークスペースが改めて Reinstall to Workspace を通るまで何の効果も持たず、その再インストールより前に発行されたトークンには決して付与されない。
一連の手順を順番に示すと次のとおり。
マニフェストか OAuth & Permissions のスコープ一覧にスコープを追加する。
Reinstall to Workspace をクリックする。
OAuth & Permissions に表示されているトークンを、保存済みのシークレットと突き合わせる。再インストールで新しい bot トークンが発行されることもあるが、それは保証されていない -- Slack のドキュメントもそこまでは言い切っておらず、本番のリファレンス実装で再インストールを繰り返し観測した限りでは、トークンが新しくなることもあれば、同じトークンが返ってくることもあった。
トークンが変わっていた場合は、新しい値を Worker のシークレットとして設定し、それが機能することを確認してから(Worker Backend: シークレットと設定)古いトークンを無効とみなす -- Slack は再インストールに伴って古いトークンを自動的に失効させるわけではないので、急ぐ必要はない。変わっていなければ、ローテーションするものは何もない。
デプロイする。ステップ 4 が該当していればここでローテーション後のシークレットが反映され、新しいスコープに依存するコードもここで配信される。
新しいスコープが解放するイベントサブスクリプションを有効化する。スコープを付与しただけでは、それが可能にするイベント種別の購読が遡って始まるわけではない。