RailsアプリでTwitterログインを実装する方法をまとめます。
##deviseの導入
メールアドレスやSNSアカウントを用いてのログインを、簡単に実装するGem「devise」と、OAuth認証に必要なGem「omniauth」「omniauth-twitter」を導入します。
gem 'devise'
gem 'omniauth'
gem 'omniauth-twitter'
#envファイルで環境変数を管理する用のgemです。合わせてインストールしておきましょう
gem 'dotenv-rails'
続いて、bundle installを行います。
bundle install
※ライブラリはサーバーの起動時に読み込まれるので、ここでいったんサーバーを停止し、再起動しましょう。
##deviseの設定
アプリケーションにdeviseをインストールします。
rails g devise:install
1から4までのステップが書かれた英文が表示されるので、指示通りにコーディングします。
###デフォルトURL
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }をconfig/environments/development.rbに追加します。
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
・・・(略:場所はどこでも良いです)
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
end
###root_urlを指定
ルートURLにアクセスした際のページを作成します。
rails g controller Pages index
Pagesコントローラーには、indexアクションと、ビューファイルindex.html.erbを追加しています。
###フラッシュメッセージを指定
ログインが成功した際に表示する、フラッシュメッセージを、application.html.erbの
・・・(略)
</head>
<body>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
###devise用のviewを作成
rails g devise:views
app/views/devise/以下にファイルが作成されます。
##Userモデルを作成
rails g devise user
※モデル名なので単数形
これにより、dbフォルダ下にマイグレーションファイルが作成されます。
##ユーザーモデルを編集
user.rbのdevise:以下に「:omniauthable」を追加します。
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :omniauthable
###データベースにカラムを追加
deviseはデフォルトでメールアドレスとパスワードした扱うことができません。ツイッターログインで扱うデータのカラムをあらかじめ追加しておく必要があります。
以下のカラムを追加します。
- ユーザーID(uid)
- プロバイダー(provider)
- アカウント名(name)
- アカウントID(nickname)
- 場所(location)
- 画像(image)
rails g migration AddColumnsToUsers uid:string provider:string name:string nickname:string location:string image:string
ここまで終わったら、以下マイグレーションを実行します。
rails db:migrate
##Twitter Developerの登録
API Keyと、Secret Keyを取得します。(省略)
###取得した2つのキーを貼り付け
Devise.setup do |config|
・・・(略)
config.omniauth :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']
end
APIキー自体はenvファイルに記入します。
TWITTER_KEY="XXXXXXXXX"
TWITTER_SECRET="XXXXXXXXXXXXXXX"
.gitignoreファイルに以下を追加します。
/.env
###Userモデルを編集する
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :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],
image: auth.info.image,
name: auth.info.name,
nickname: auth.info.nickname,
location: auth.info.location
)
end
user
end
private
def self.dummy_email(auth)
"#{auth.uid}-#{auth.provider}@example.com"
end
end
Teitter認証の際に取得した各データを、データベースに格納しています。メールアドレスがない場合はdevise側でエラーが発生してしまうので、ダミーのアドレスを作成しています。
###コールバックの設定
app/controllers/以下に「users」フォルダを作成し、その下に「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?
print("persisted true")
flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
sign_in_and_redirect @user, event: :authentication
else
print("persisted false")
session["devise.#{provider}_data"] = request.env['omniauth.auth']
redirect_to controller: 'sessions', action: 'new'
end
end
end
###ルーティングの設定
config/route.rbのdevise_forを、以下のように編集します。
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
###ビューファイルを整える
ビューファイルを以下のように整えます。
<%if user_signed_in? %>
<%=current_user.email%>
<%=current_user.name%>
<%=current_user.nickname%>
<%=current_user.image%>
<%=current_user.location%>
<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
<%else%>
<%= link_to "ログイン", new_user_session_path %>
<%end%>
以上でツイッター認証ログインが可能になりました。