LoginSignup
14
3

More than 5 years have passed since last update.

railsでslackとOAuth + メッセージ投稿

Last updated at Posted at 2018-02-25

内容

本記事はrailsアプリから、ユーザのSlackと連携するためのアクセストークンをOAuthで取得して、メッセージを送る処理を書いています。
なので、自分の所属するチームにメッセージを送るというより、見知らぬ誰かのチームに送るサービスをイメージしています。

Incomming webhooks使えばOAuthいらんやん、とか言われそうですが
ユーザ側で設定しなきゃいけないのは面倒くさいと思うので。
(普段slackにブラウザでアクセスする人ってあんまいないんじゃ、、、とかは気にしない)

環境

  • macOS High Sierra 10.13.3
  • ruby 2.5.0
  • rails 5.1.4

事前準備編

Slackにチーム登録

Slackにはチームがすでに登録されている前提です。

Slackにアプリ登録

まずは、SlackAPIを叩くためにSlackにアプリを登録しておきます。

ブラウザでslackにログインしてから、こちらのurlにアクセス
https://api.slack.com/

右上に表示される"Your Apps"をクリック
your_apps.png

"Create an App"クリック
create_an_apps.png

表示されるフォームで適当にアプリの名前を入力して、アプリを登録したいチームを選択
create_app.png

Basic InformationのApp CredentialsでClient IDとClient Secretを控えておきます。
credentials.png

ちなみにClient Secretは関係者以外に見せてはいけないので、管理には注意してください。
git載せるダメ、絶対

下にVerification Tokenというものもありますが、メッセージを送るだけならば不要です。

続いて、OAuth連携をするための設定を行います。
左サイドのOAuth & Permissionsをクリックします。

Redirect URLsはslackで認証後に自分のアプリに戻るためのurlです。
後でいくらでも変更可能なので、適当に登録しておきます。
ここでは認証後にhttp://localhost:3000/slack/auth へ戻してもらうことにしましょう。
意外に気づかないのが、"Add a new Redirect URL"で記入した後、"Save URLs"を押さないと登録されないので注意。
redirect_uri.png

次は下にスクロールしてScopeを設定します。
このアプリが認証されたユーザに対して行うことができる操作をここで設定します。
twitterとかでアプリ連携する時に、「このアプリは〇〇を行うことができます」みたいな感じで表示されるアレ

今回はメッセージが送れれば良いので、"Send messages as hogehoge (chat:write:bot)"のみ、
権限は最小限にするのが鉄則だから不用意になんでもかんでも設定しない
これもSave Changesをお忘れなく。
scopes.png

これでslack側の設定は完了!!:tada:

rails

前準備

細かい所は気にしないでslack連携を行う場所を適当に作っていきます。

rails new slack_auth
rails generate controller slack index
config/routes.rb

Rails.application.routes.draw do
  resources :slack do
    collection do
      get :auth
    end
  end
end

今回はslackへのメッセージ送信用にslack-apiというgemを利用します。
slackで提供されるapiのラッパーなので、
必要なパラメータはcurlなどで叩く場合と基本的に同じなはずです。

Gemfileに以下を追記してbundle install実行

Gemfile
gem 'slack-api'
bundle install

使用するときはrequireしてあげる必要があるので、initializersにそれ用のファイルを追加します。

config/initializers/gems.rb
require "slack"

Slackの承認ページアクセス

Slackの承認ページへアクセスするための処理を作りましょう。
今回はnewアクションでリダイレクトさせるようにします。
クエリパラメータには要求するscopeと、先程取得したclient idをつけてください。
実際に利用する際は環境変数を使うなどして、直接書かないことをおすすめします。

app/controllers/slack_controller.rb
class SlackController < ApplicationController
  def index
  end

  def new
    redirect_to ("https://slack.com/oauth/authorize\?scope\=chat:write:bot\&client_id\=" + "取得したclient_id")
  end

  def auth
  end
end
app/views/slack/index.html.erb
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>

<h1>Slack#index</h1>
<%= button_to 'Slack OAuth', new_slack_path, :method => :get %>

index.png

ボタンをクリックすると、Slackの承認ページが表示されます。

slack.png

アクセストークン要求

Authorizeを押すと、
先程redirect_urlで設定した指定したurl(/slack/auth)へ
codeというクエリパラメータが付加された状態でリダイレクトされます。

アクション側ではこのcodeを使って、アプリからSlackへアクセストークンを要求することになります。
slack-apiでSlackクラスが用意されるため、これでアクセストークンを取得します。
例によってclient_secretは直接書かないことをおすすめします。

app/controllers/slack_controller.rb
  def auth
    auth_result = Slack.oauth_access({client_id: "取得したclient_id", client_secret: "取得したclient_secret", code: params[:code], scope: "chat:write:bot"})

    if auth_result["ok"]
      redirect_to slack_index_path, notice: "テスト"
    else
      redirect_to slack_index_path, alert: "error: " + auth_result["error"]
    end
  end

auth_resultの中身はこんな感じ

# 成功した時
{"ok"=>true,
 "access_token"=>"xxxx-xxxxx-xxxxx-xxxxx-xxxxx",
 "scope"=>"identify,chat:write:bot",
 "user_id"=>"XXXXXXXXX",
 "team_name"=>"slaaaaack",
 "team_id"=>"XXXXXXXXX"}

# 失敗した時
{"ok"=>false, "error"=>"code_already_used"}

このアクセストークンがSlackへの連携処理を行う際に必要な情報になります。
現状トークンに有効期限はなく、ユーザが再生成しない限り
同じトークンを使い続けられるそうです。
https://qiita.com/subarunari/items/3e4c6060fcefd4c65257

メッセージ投稿

取得したアクセストークンを使って、Slackにメッセージを投稿します。
メッセージ投稿はユーザの表示名と投稿先のチャンネルを指定して行います。

app/controllers/slack_controller.rb
  def auth
    auth_result = Slack.oauth_access({client_id: "取得したclient_id", client_secret: "取得したclient_secret", code: params[:code], scope: "chat:write:bot"})

    if auth_result["ok"]
      Slack.client({token: auth_result["access_token"]})
           .chat_postMessage(text: "グッド!!", username: "test_auth", channel: "#random")

      redirect_to slack_index_path, notice: 'slackにメッセージを送りました'
    else
      redirect_to slack_index_path, alert: "error: " + auth_result["error"]
    end
  end

Slackの承認ページでAuthorizeを押すと

[画面]

index_2.png

[Slack]

slack_message.png

無事メッセージが送られました:tada:

14
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
3