【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>
最後にルーティングの設定です。
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の記事、あれ更新日時が検索結果に反映されるせいで、記事内に「現在は古いですのでこちらを参考に」みたいなザコい更新でも新規記事として上にくるんですよね。
基本的に多分コーディング関連の記事は新しいものを中心にリサーチすると思うので、個人のブログでも変に更新日を反映させないでほしいところです。