sponsored link

【Rails5】deviseとomniauthを使ったTwitter認証

色々な記事を参考にしたけど、結局色々な記事を見る羽目になったので個人的にまとめておきます。

環境変数等はガン無視でとりあえず実装します。

Twitterのデベロッパ申請は通っててAPIキーとAPIシークレットキーは持ってるものとします。

1. gemを入れる

Gemfileに以下のGemを入れて bundle install する。

gem 'devise'
gem 'omniauth'
gem 'omniauth-twitter'

2. まずはdeviseでログインを実装

とりあえずコマンドラインにこれを打つ

$rails g devise:install

次に devise と紐ついた User モデルを作成しマイグレート

$rails g devise user
$rake db:migrate

最後にサーバーを立ち上げて ~/users/sign_in にアクセスするとログイン画面ができてるはずです。

3. OmniAuthでTwitterの認証を実装

先ほどのUserモデルにカラムを追加します。ユーザーid(uid)はUserの確認に用います。

$rails g migration AddColumnsToUsers uid:string provider:string
$rake db:migrate

ここで引っ張ってこれるあたいは他にも色々あるのでomniauth-twitterのReadme参照
https://github.com/arunagw/omniauth-twitter


config/initializer/devise.rb の中に下記の3行目を追加します。
API Key, API secret, 〇〇 は適当なものを当てはめてください。

Devise.setup do |config| 
 # ...
  config.omniauth :twitter, 'API key', 'API secret', callback_url: "https://〇〇/users/auth/twitter/callback"
end

ローカルならコールバックは http://127.0.0.1:3000/users/auth/twitter/callback にしておけばいいかな


deviseメソッドに認証用のメソッドを追加し、userモデルも編集します。
app/model/user.rb を以下のように編集

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :trackable, :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.skip_confirmation!
    user
  end
     
  private
     
  def self.dummy_email(auth)
    "#{auth.uid}-#{auth.provider}@example.com"
  end
end

emailにはダミーを入れます。user.skip_confitmation!は確認用メールの送信を防ぎますが正直今はどっちでもいいのでコメントにしてます。


app/controllers/users/omniauth_callbacks_controller.rbに以下のコードを追加
(usersフォルダと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

ビューを作成します。

$ rails g controller home index

app/home/index.html.erb を以下のように編集します。

<ul>
  <%if user_signed_in? %>
    <li><%=current_user.email%></li>
    <li><%=current_user.name.uid%></li>
  
    <li><%= link_to "ログアウト", destroy_user_session_path, method: :delete %></li>
  <%else%>
    <li><%= link_to "ログイン", user_twitter_omniauth_authorize_path %></li>
  <%end%>
</ul>

最後にルーティングの設定です。
config/routes.rbを下記のように編集します。

Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' } 
  root to: 'home#index'
  get 'home/index'

end

4. 完成

rails s でサーバーを立ち上げたらホーム(127.0.0.1)にあるログインボタンを押して、ログインできた後に画面にユーザーIDやダミーのメアドが出て入れば完成です。

  

あとがき

Qiitaの記事、あれ更新日時が検索結果に反映されるせいで、記事内に「現在は古いですのでこちらを参考に」みたいなザコい更新でも新規記事として上にくるんですよね。

基本的に多分コーディング関連の記事は新しいものを中心にリサーチすると思うので、個人のブログでも変に更新日を反映させないでほしいところです。

コメント