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

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

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

はじめに

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

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

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

【投稿内容】

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

本記事でやること

本日はログインgemであるsorceryを使用してSlackログインを実装する記事を書いていきたいと思います!しかし、かなりやることが多いので二回の記事に分けて行いたいと思います!

SlackログインはSorceryでできるようになった!

実は自分がslackログインを実装したのはdeviseとomniauthのgemを組み合わせで行いました。理由としてはsorceryではエラーが起きていたからです。自分は1、2週間かけてsorceryでslackログインができない理由を調査したことがあります。しかし、どうやってもできなかったので明らかにgem側の問題と結論づけました。というのもslack.rbというsorceryのslack認証ファイルの更新が5年前で止まっていたからです。

しかし、最近なぜか更新されていることを発見し、Pull Requestが投げられていることを確認しました!

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

これでsorceryでもslackログインができるようになったらしいので自分も本当にできるようになったか確認したところ、しっかりとできるようになっていました!!!!そのため、この記事でその方法を詳しく紹介します!

セットアップ

Slackログインを実装する前に、ユーザーモデルの作成など必要な設定をしておきます。基本的には公式と同様の流れで設定を行います。

GitHub - Sorcery/sorcery: Magical Authentication

gem 'sorcery'
$ bundle install

下記コマンドを実行してマイグレーションファイルやsorceryの設定ファイルを作成

$ rails generate sorcery:install
Running via Spring preloader in process 74291
      create  config/initializers/sorcery.rb
    generate  model User --skip-migration
       rails  generate model User --skip-migration 
Running via Spring preloader in process 74315
      invoke  active_record
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      insert  app/models/user.rb
File unchanged! The supplied flag value not found!  app/models/user.rb
      create  db/migrate/20211003000947_sorcery_core.rb

作成されたマイグレーションファイルは以下のようになります。

class SorceryCore < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      t.string :email,            null: false
      t.string :crypted_password
      t.string :salt

      t.timestamps                null: false
    end

    add_index :users, :email, unique: true
  end
end

変更は特に必要ないのでそのままrails db:migrateします。

$ rails db:migrate

マイグレーションファイルの設定に合わせてモデルのファイルにもバリデーションを設定しておきます。

class User < ApplicationRecord
  authenticates_with_sorcery!
  validates :email, uniqueness: true, presence: true
  validates :password, presence: true
end

ここまでで必要な設定は完了です!

Slack Developersでの設定

まず下記ページにアクセスします。

Slack API: Applications | Slack

下記のような画面になっているので、上部にある「Create New App」をクリックします。

https://i.gyazo.com/58bcb7334b8c24a1deb0ccd73549a2aa.png

すると以下のようなモーダルが開きました。

Choose how you’d like to configure your app’s scopes and settings.

「アプリのスコープや設定をどのように設定するかを選択してください。」と説明されています。ここではSlack標準の設定である「From scratch」を選択します。

https://i.gyazo.com/138fa9057a3cc9bf95dfd027a8509d4c.png

次に別のモーダル が開きアプリの名前と開発ワークスペースを選択します。

https://i.gyazo.com/6ecff661176ab602c5833747d9c3b8e5.png

アプリの名前は分かりやすいものにしておきます。

  • App Name → 「slack-sorcery-login」

開発ワークスペースとはSlackアプリを開発する際に使用するワークスペースです。既に参加しているワークスペースでも構いませんが、アプリように新しく開発ワークスペースを作成したほうがいいと思います。ワークスペースの作成方法については以下のリンクから作成してください。

Slack ワークスペースを作成する

自分は新しく「slack-sorcery-login」をいうワークスペースを作成して、それを開発ワークスペースとして選択しました。

  • Pick a workspace to develop your app in: → 「slack-sorcery-login」

最後に「Create App」を押してアプリを作成します。成功すると下記のようなSlack Appの開発画面に遷移します。これでアプリの作成は完了です。

https://i.gyazo.com/641691c8ccd47adbc39e5ccbc91c4d6f.png

最後にClient IDとClient Secretを確認します。上記の画面を下にスクロールすると確認できます。後ほどこちらは使用します。

https://i.gyazo.com/7a83a9555a36ca1589bbaca3c8e605b6.png

Slackログイン用のファイル設定

アプリを作成できればいよいよSorceryのSlack認証機能を実装します。基本的にはSorceryの公式の外部認証のwikiに沿って実装します。

Authenticationテーブル & モデルの作成

External · Sorcery/sorcery Wiki

最初に外部認証用のテーブルを作成します。下記コマンドでマイグレーションファイルを作成します。

$ rails g sorcery:install external --only-submodules
gsub  config/initializers/sorcery.rb
File unchanged! The supplied flag value not found!  app/models/user.rb
      create  db/migrate/20211003005016_sorcery_external.rb

作成されたマイグレーションファイルは下記になります。

class SorceryExternal < ActiveRecord::Migration[6.1]
  def change
    create_table :authentications do |t|
      t.integer :user_id, null: false
      t.string :provider, :uid, null: false

      t.timestamps              null: false
    end

    add_index :authentications, [:provider, :uid]
  end
end

providerとは外部認証を提供しているアプリを指します。TwitterFacebook、LINEなどが挙げられます。そしてマイナーではありますがSlackもその中の一つです。

変更は特に必要ないのでそのままrails db:migrateします。

$ rails db:migrate

次に作成したauthenticationsテーブルに合わせてモデルも作成します。理由はわからないのですが、rails g sorcery:install external --only-submodulesではモデルのファイルは作成されません。よってモデルは別で作成する必要があります。

それではモデルを作成します。マイグレーションファイルはもう既に作成しているので、--migration=falseオプションを付けています。

$ rails g model Authentication --migration=false

Authenticationモデルにbelongs_to :userを追加

# app/models/authentication.rb
class Authentication < ActiveRecord::Base
  belongs_to :user
end

Userモデルにはhas_many :authentications, dependent: :destroyaccepts_nested_attributes_for :authenticationsを追加

# app/models/user.rb
class User < ApplicationRecord
  authenticates_with_sorcery!
  validates :email, uniqueness: true, presence: true
  validates :password, presence: true
  has_many :authentications, dependent: :destroy
  accepts_nested_attributes_for :authentications
end

Sorcery.rbの設定

次にsorcery.rbでSlackの認証の設定を記述します。sorcery.rbで「Slack」と検索すると下記の部分が確認できます。

# config.slack.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=slack"
# config.slack.key = ''
# config.slack.secret = ''
# config.slack.user_info_mapping = {email: 'email'}

コメントアウトを外しconfig.slack.keyにはClient ID、config.slack.secretにはClient Secretを記述します。しかし、直書きするのはよくないので環境変数はcredentialsに定義します。

config.slack.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=slack"
config.slack.key = Rails.application.credentials.dig(:slack, :clinet_id)
config.slack.secret = Rails.application.credentials.dig(:slack, :client_secret)
config.slack.user_info_mapping = {email: 'email'}

credentialsの編集方法は下記Qiitaを参照ください。

Rails5.2から追加された credentials.yml.enc のキホン - Qiita

$ EDITOR="vi" bin/rails credentials:edit

下記のように記述します。

slack:
  client_id: 2572424345441.2562011521556
  client_secret: 6627c1e772a94532566a2c8588927608client_secret

また、どの外部認証を使うかを明記する必要があるため、sorcery.rbの83行目のコメントアウトされている部分のコメントアウトを外し、slackを追加します。

config.external_providers = [:slack]

また、「user.authentications_class」とsorcery.rbで検索し、外部認証のクラスを明記するために下記のようにAuthenticationクラスを指定します。

# --- user config ---
  config.user_config do |user|
  ...

    # -- external --
    user.authentications_class = Authentication
    ...

  end

適当なログインページを作成

現状どこにもviewを書いていないのでログインページを適当に作ります。

ログインページを適当に追加

現状どこにもviewを書いていないので、ログインするためのページを適当に作ります。

$ rails g controller home index

次にコントローラーを編集します。sorceryのヘルパーメソッド、require_loginを追加します。

# app/controllers/home_controller.rb
class HomeController < ApplicationController
  skip_before_action :require_login
  def index ;end
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :require_login
end

routes.rbにHomeControllerのindexアクションをルートパスに指定します。

Rails.application.routes.draw do
  root to: "home#index"
end

viewも作っておきましょう。中身は記述しなくても良いのでファイルだけ作成しておきます。

<!-- app/views/home/index.html.erb -->

本記事での実装はここまでとします!次回でslackログインを最後まで実装します!

参考記事

【Rails】SorceryでTwitter認証

GitHub - Sorcery/sorcery: Magical Authentication