FirebaseアプリからSlackへ通知を行う。アクセストークンは手動で設定する編。


背景

WEBサービス運用していて、ユーザに情報を送信したいケースなどがあるとおもいますが、そのユーザが使用しているSlackに通知を飛ばせたら便利ですよね。
シンプルにやろうとするならIncoming Webhook のURLをもらうのが楽なんですが、任意のユーザにWEBサービスを広くつかってもらう事を考えた場合、そのWebhookのURL をどう受領するかや、各ユーザがSlackでWebhookを設定をするの?などいろいろと課題があります。

さて個々のユーザに「あなたのSlackへの通知(POST)を許可してもらう」こと、これってつまりOAuthを用いた認可機構があると便利なわけですが、Slack APIを用いた Slack App がまさにOAuthの機構だったりします。

ってことで今回は OAuthをつかった、こんな処理シーケンスの Slack Appを作ってみます。

  • WEB上のリンクをクリックしたら「 あなたのアカウントであなたのSlackに投稿を行うアプリだけど、許可する?」って認可画面が表示されて
  • ユーザが認可したら、アプリ(Slack App)が そのユーザとしてSlackに投稿できるようになる

まあ通知したいだけなら「そのユーザとして通知する」とかにはしないのですが、URLだけ分かると投稿出来ちゃう Incoming Webhook とは違うAPIを、今回はつかってみようとおもいます1

やってみる(作成)

早速Slack App を作っていきます。

Slack App (Hello World App)の作成

https://api.slack.com/apps にアクセス。サインインしてねと言われるので、言われるがままに。

初めてアプリを作るとき以外は、自分が作成したアプリが並んでいるのですが、初回はこんな画面。Create an App を選択。

(もしくはログイン状態によってはこのような画面遷移にならないこともあるぽいですが、とりあえず「Create an App」を押せればOKですorz。。)

下の画像の赤枠のメッセージを見ると、あるSlack Appはひとつのワークスペース配下で管理するという考え方のようですね。てことでそのワークスペースを選んで、Create Appを押します。

トップページ。機能追加のメニューなどがあります。

下にスクロールしていくと、OAuth関連でおなじみのclient_id/client_secret の情報だったり、

アプリのアイコンや説明などの設定項目が。

とりあえず、一覧してみました。次に権限を追加します。

アプリに、Slack上の処理を許可する画面を設定する

このアプリに、Slack上のある処理をさせてよいかを許可する画面、ちゃんというと、

  • 認可サーバ(Slackサーバ)が、
  • このアプリ(OAuthクライアント)に対して
  • リソースオーナーであるあなたのSlackに対して、
  • これとこれ(scopeという)をやることが出来ちゃうけど、許可していい?

と表示する画面の内容を設定します。たとえば「ユーザとしてメッセージを送信できる」権限を与えているアプリを作成すると下記のような感じになります。よくあるOAuthの認可画面です。

また許可する「これ」とはたとえば、「あなたのSlackにボットとして投稿する」や「あなたのSlackのメンバ一覧を取得する」や「あなたのアカウントとしてSlackに投稿する」などのオペのことをさしています。

さてさっそく、上記のようになる権限の範囲(OAuthのscope)を設定します。トップページにあった機能追加のメニューで「Permissions」を選択。

次画面で、scopeを設定するブロックがあるので、Select Permission Scopesで「chat:write:user(ユーザとしてメッセージを送信できる)」を選択し「Save Changes」をクリック。

権限を追加できました。ちなみにこのscopeは複数設定が可能です。

動かしてみる

ためしに、自分のワークスペースにアプリをインストールする

ワークスペースにSlack Appをインストールするには、通常はWEB画面のリンクから認可画面を表示し、ユーザが許可をすることでインストールされるわけですが、このアプリ開発画面からこのユーザの認可画面を表示し、自分のワークスペースにアプリをインストールすることができます。
先ほどまでDisableになっていた、このページ一番うえの「Install App to Workspace」がクリックできるようになっているので、クリックすると、、

認可画面になるので「許可する」をクリックします。

元の画面にリダイレクトされてきました。画面に OAuth Access Token という欄がでてきて、値が表示されていますが、通常のOAuthの処理シーケンスに則って、chat:write:user のscopeをもったアクセストークンが取得できたようですね。

さて今回の処理の流れが通常のOAuthの処理シーケンスと言いましたが「通常のOAuthの処理シーケンス」ってのは、こんな感じのことです。

今回のシーケンスも上記のような感じでしたよね。。

Curlから実行

さて あるスコープをもったアクセストークンが得られたので、これをつかってアプリを動かしてみます。

OAuth Permission scopes ここを見ると、scopeとそのscopeをもったトークンで使用可能なAPIの一覧が整理されていますので、「chat:write:user」のなかをみてみると、

  • chat.delete - Deletes a message.
  • chat.meMessage - Share a me message into a channel.
  • chat.postEphemeral - Sends an ephemeral message to a user in a channel.
  • chat.postMessage - Sends a message to a channel.
  • chat.update - Updates a message.

などがありました。chat.postMessage のページの仕様に基づいて、トークンをつかってAPIを呼び出してみます。

$ cat message.json
{
    "channel":"#general",
    "text": "今日は!"
}

$ curl https://slack.com/api/chat.postMessage -X POST \
 -H 'Content-Type: application/json; charset=UTF-8' \
 -H 'Authorization: Bearer xoxp-547xxxxxxxxxxxx' \
 --data-binary @message.json


{
  "ok": true,
  "channel": "CG4xxxx",
  "ts": "154xxxxxxx.000700",
  "message": {
    "bot_id": "BG3JW9GGJ",
    "type": "message",
    "text": "今日は!",
    "user": "UGxxx2",
    "ts": "154xxxxxxx.000700"
  }
}

認可したユーザのアカウントで、メッセージが投稿されましたね!

いったんまとめ

さて今回は開発者自身のアカウントに対して「Slack Appの開発画面」から、OAuthの認可画面を呼び出して、アクセストークンを取得しました。そしてそのアクセストークンは、通常のOAuthのBearerトークンとして使用する事が出来ました。

ちなみに、このアクセストークンをSlack Appに取得させることを「ワークスペースにSlack Appをインストールする」と表現するわけですね。

さて自分だけでつかうSlack Appであれば、この得られたトークンをつかってFirebase Functionsからでも AWS Lambdaからでも自由に、認可された範囲でAPIをコールできるのでこれでおしまいです。先ほどのシーケンス図をもういちど載せますが、つまりこんなシーケンスにすればOKです。

上記のCurlのところをFirebaseやLambdaで構築すればOKってことですね。

でも、任意のSlackユーザに使ってもらうには、アクセストークンをアプリにわたすシーケンスなどをもうすこし整理する必要があります。具体的には下記のシーケンスになりそうです。

  • Access Tokenは Slack Appの開発画面で目視で確認するのではなく、アプリケーションがDBMSなどへ永続化する
  • そのためにOAuth認可サーバのリダイレクト先を、自前のロジックが動かせるサーバに設定する
  • Curlで実行した箇所を、たとえばFirebase Functionsなどで定期実行するようにする。そのロジックは先のDBMSからアクセストークンを取り出す

だいたい、こんな感じですね。長くなったので今回はココまで。。

というわけで次回は、図中の「Slackアプリの管理画面」を作成し、あるユーザが「Add to Slack」のリンクをクリックする想定でアプリを作ってみようと思います。

おつかれさまでした。

関連リンク


  1. またもちろん、そのユーザとして投稿させる権限とかふつう許可しない、ってなるでしょうけどね。。