13note.

なんか調べたりまとめたり感想言ったりする語彙力不足及び眠気と戦うブログ

RoR 5 Twitter Oauth認証

MarkDown記法じゃないとコードハイライト使えないとは…しかも一度保存した記事はMarkdownに変えられないとは…

.envに環境変数の設定

touch .env

上記で.envファイルを作成し、控えておいたAPIKey、SecretKeyを定義する。

TW_APP_KEY="hoge"
TW_APP_SECRET="fuga"

deviseのinitializerに環境変数追記する

以下を追加。

# ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
  config.omniauth :twitter, ENV['TW_APP_KEY'], ENV['TW_APP_SECRET']
Userモデルの修正

deviseによって作成したuserモデルは以下のようになっている。

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end

この「devise」に「:omniauthable」を追加。 また、find_for_oauthメソッドを追加する。(モデルに追加したuidとproviderでのユーザ検索、また該当がなければuserモデルを作成する関数)(新規作成用にダミーEmailを作成するprivate関数も追加)

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :omniauthable


   def self.find_for_oauth(auth)
     user = User.where(uid: auth.uid, provider: auth.provider).first

     unless user
       user = User.create(
         uid:      auth.uid,
         provider: auth.provider,
         email:    User.dummy_email(auth),
         password: Devise.friendly_token[0, 20]
       )
     end

     user
   end

private

   def self.dummy_email(auth)
     "#{auth.uid}-#{auth.provider}@example.com"
   end

end
OmniauthCallbacksControllerの継承クラスを作成する

controller 以下にusersディレクトリを作成、omniauth_callbacks_controller.rbを作成する。

mkdir controllers/users
cd controllers/users
touch omniauth_callbacks_controller.rb

omniauth_callbacks_controller.rb の内容は以下。

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def twitter
    callback_from :twitter
  end

  private

  def callback_from(provider)
    provider = provider.to_s

    @user = User.find_for_oauth(request.env['omniauth.auth'])

    if @user.persisted?
      flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
      sign_in_and_redirect @user, event: :authentication
    else
      session["devise.#{provider}_data"] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end
routeファイルの修正

omniauth_callbacksを追加する。

Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root to: 'tasks#index'
  resources :tasks
end

やったことはこれで一通り。 deviseの標準のusers/sign_up用viewには予めtwitterでの認証が対応されている。 twitterに対して要求する権限とかはどこかで設定するのだろうか?(読み書き可になっていた。どういう意味の「書き」なんだろう…)