大ちゃんの駆け出し技術ブログ

RUNTEQ受講生のかわいいといわれるアウトプットブログ

【無職に転生 ~ 就職するまで毎日ブログ出す④】【Rails】sorceryを使ったSlackログイン②

はじめに

こんにちは、大ちゃんの駆け出し技術ブログです。

タイトルにあるとおり【無職に転生 ~ 就職するまで毎日ブログ出す】というチャレンジをしています!!!大人気アニメのタイトルをまるパクリした毎日投稿チャレンジです。

RailsやらRubyやらSQLやらその他Webの知識やらが色々と抜け落ちているのを感じており、知識の定着のためにもアウトプットする機会を増やすためです。加えて、退職して文字通り無職に転生しましてプロニートになり、毎日時間に余裕ができたので引き締めるためにも毎日投稿を思い至りました!

【投稿内容】

  • SQLの難しい処理 (副問合せ、JOINとか複雑な処理が書けない)
  • Rails全般 (純粋に必要な知識が多すぎる、網羅的な理解が足りない)
  • Rubyのあまり使わないメソッドや記述方法 (あまり重要ではないけど特に)
  • Web知識全般 (クッキーやら、セッションやらなんとなくで理解しているものの自分の言葉で説明できない)
  • 書籍 (スタートアップ企業に勤めるので、自分が会社に与える影響やパフォーマンスを高めるためビジネス書を読んでいきます。)

本記事でやること

本日はログインgemであるsorceryを使用してSlackログインを実装する記事の続きです!前回の記事はしたのリンクから参照ください!

【無職に転生 ~ 就職するまで毎日ブログ出す③】【Rails】sorceryを使ったSlackログイン① - 大ちゃんの駆け出し技術ブログ

Slackログインの実装

いよいよSlackログインを実装します!

コントローラーの作成

Slackログインをするためのコントローラーを作成します。

$ rails g controller Oauths oauth callback

中身は下記のように実装します。下のコードの説明は後ほどSlackログイン実行時に説明しますので今はコピペだけでOKです!

# app/controllers/oauths_controller.rb
class OauthsController < ApplicationController
  skip_before_action :require_login

  def oauth
    login_at(auth_params[:provider])
  end

  def callback
    provider = auth_params[:provider]
    if (@user = login_from(provider))
      redirect_to root_path, notice: "#{provider.titleize}でログインしました"
    else
      begin
        @user = create_from(provider)
        reset_session
        auto_login(@user)
        redirect_to root_path, notice: "#{provider.titleize}でログインしました"
      rescue StandardError
        redirect_to root_path, alert: "#{provider.titleize}でのログインに失敗しました"
      end
    end
  end

  private

  def auth_params
    params.permit(:code, :provider)
  end
end

routes.rbの設定

これも公式wikiと同じです。

# config/routes.rb
post "oauth/callback", to: "oauths#callback"
get "oauth/callback", to: "oauths#callback"
get "oauth/:provider", to: "oauths#oauth", as: :auth_at_provider

Bootstrapの追加

ここは飛ばしても問題ないです。後ほどアプリを拡張するかもしれないので念のため入れておきます.

$ bin/yarn add bootstrap@4.4.1 jquery@3.5.1 popper.js@1.16.1
// app/javascript/packs/application.js
import "bootstrap"
import "bootstrap/scss/bootstrap.scss"

viewにリンクを追加

Slackログイン用のリンクを前回適当に作ったページに追加します。

<%= link_to 'Login with Slack', auth_at_provider_path(provider: :slack), class: "btn btn-primary btn-block" %>

ですが、ログインしたことがわかるようにしたいので下記のように記述してください。ヘルパーメソッドlogged_in?でログインしていなければリンクを表示、していれば「ログインししました!」というメッセージが表示されます。

<div class="container p-5">
  <% if logged_in? %>
    <div>ログインしました!</div>
  <% else %>
    <%= link_to 'Login with Slack', auth_at_provider_path(provider: :slack), class: "btn btn-primary btn-block" %>
  <% end %>
</div>

Ridirect URLの設定

OauthでよくあるRiderect URL(コールバック)を設定します。GitHubTwitterのdeveloperではlocalhostのURLで指定できますが、SlackではhttpsのURLを指定する必要があります。よってngrokを使用してhttpsのURLを生成します。

ngrokの設定を反映させるために下記の記述をdevelopment.rbに追加します。

# config/environments/development.rb
Rails.application.configure do
.
.
  config.hosts << '.ngrok.io'
end

ngrokを起動します。

$ ngrok http 3000
・
・
Version                       2.3.35                                                                             
Region                        United States (us)                                                                 
Web Interface                 http://127.0.0.1:4040                                                              
Forwarding                    http://61f8-111-239-158-158.ngrok.io -> http://localhost:3000                      
Forwarding                    https://61f8-111-239-158-158.ngrok.io -> http://localhost:3000

httpsのURLを確認します。自分の場合は下記URLです。

https://61f8-111-239-158-158.ngrok.io

このURLをコピーしてsorcery.rbを開き、Slackの設定の箇所を探します。そしてconfig.slack.callback_urlの箇所を下記のように設定します。

config.slack.callback_url = "https://61f8-111-239-158-158.ngrok.io/oauth/callback?provider=slack"
config.slack.key = Rails.application.credentials.dig(:slack, :client_id)
config.slack.secret = Rails.application.credentials.dig(:slack, :client_secret)
config.slack.user_info_mapping = {email: 'email'}

https://i.gyazo.com/e519bc3cd3add78050cc7af98167c599.png

設定したURLをコピーします。

https://61f8-111-239-158-158.ngrok.io/oauth/callback?provider=slack

次にSlackの開発ページを開いて左ペインの「OAuth & Permissions」をクリックします。

次に「Redirect URLs」という項目があるのでそこに先ほどコピーしたURLを貼り付けます。

  • 「Add New Redirect URL」をクリック
  • フォームが出てくるのでそこにコピーしたURLをペースト
  • フォームの横にある「Add」をクリック
  • 「Save URLs」をクリック
  • 「Success!」が表示

https://i.gyazo.com/308f06440199f60db3096787ecc41710.gif

これでRedirect URLの設定が完了です。

Slackログインを確認

これで必要な設定は全て完了しましたので早速Slackログインを確認します。ngrokで生成されたURLでブラウザを開きます。

https://i.gyazo.com/040e53c18275e4b6324143c67c80c8a2.png

リンクを押すとSlackの認証画面に遷移します。

https://i.gyazo.com/ae4bafe3683bd7f43c0a8e0e730603f8.gif

Slackの認証画面で「許可する」を押します。すると画面に「ログインしました」と表示されます。

https://i.gyazo.com/3d728033461977928517c151427611c7.png

ここでログインに失敗する場合、sorceryが最新でインストールされていない可能性があります。つまり、slackログインができない状態のsorceryです。ですので、gemの処理をPRに沿って書き換えましょう。

Removes unnecessary 'token' param from request to Slack for user info. by robot-soul · Pull Request #287 · Sorcery/sorcery

変更する箇所は1箇所のみです。access_token.get(user_info_path, params: { token: access_token.token })access_token.get(user_info_path)に変更します。

# vendor/bundle/ruby/2.6.0/gems/sorcery-0.16.1/lib/sorcery/providers/slack.rb

def get_user_hash(access_token)
  response = access_token.get(user_info_path)
  auth_hash(access_token).tap do |h|
    h[:user_info] = JSON.parse(response.body)
    h[:user_info]['email'] = h[:user_info]['user']['email']
    h[:uid] = h[:user_info]['user']['id']
  end
end

終わりに

Slackログインの記事はほとんどないので実装するのは大変でした💦 このログイン方法が皆さんに使ってもらえたら嬉しいです。ただ現状OauthsControllerの処理について疑問に思っている方も多いと思います。OauthsControllerの処理の説明は長くなるのでまた今度にします!