#機能概要
「devise」のメールアドレスの新規会員登録機能に加えて、ソーシャルログイン機能も追加します。
具体的には、
ソーシャルログインリンクをクリック
▼ ▼ ▼
TwitterやFacebookに登録してあるメールアドレスを取得、パスワード入力で新規会員登録
▼ ▼ ▼
ソーシャルログインリンクをクリックすると、ログインができるようになる
という流れです。
#前提
- 会員登録に使用するモデルは「User」とします。
- 「config」のgemを使用し、定数呼び出しを行える状態
- 「devise」のメールアドレスの新規会員登録機能が実装されている状態
#事前準備
- Railsインストール(下記参照)
- Dockerでrailsローカル開発環境構築
- 定数呼び出し設定(下記参照)
- 【Rails】「config」の使い方
- devise設定(下記参照)
- 【devise】メール認証のサインアップ・イン・アウト機能
- APIキーとシークレットキーを取得。
- Twitter Developer Platform
- Facebook for Developers
Twitter Developer Platformの設定
Twitter Developer Platformでアプリを作成後、下記の作業を行います。
Website URLは、「https://example.com」など、本番のものにしておきました。
Callback URLは、下記のようにします。
https://example.com/users/auth/twitter/callback
http://localhost/users/auth/twitter/callback
ローカル環境や本番環境など、複数設定も可能です。
Privacy Policy URLとTerms of Service URLに、emailを取得のため、プライバシーポリシーと、サービス利用規約ページのURLを入力しましょう。
Permissionタブの中のAdditional permissionsは、メールアドレスの呼び出しを行うため、「Request email address」としました。
**「API key」と「API secret key」**を控えておきましょう。
Facebook for Developersの設定
Facebook for Developersでアプリを作成後、下記の作業を行います。
**「アプリID」と「app secret」**を控えておきましょう。
#手順
定数でAPIキーを呼び出せるようにする。
twitter:
twitter_api_key: 'API key'
twitter_api_secret: 'API secret key'
facebook:
facebook_api_key: 'アプリID'
facebook_api_secret: 'app secret'
再起動後、下記のように、上記で設定した情報の呼び出しが可能になります。
Settings.twitter[:twitter_api_key]
Settings.twitter[:twitter_api_secret]
Settings.facebook[:facebook_api_key]
Settings.facebook[:facebook_api_secret]
Gemインストール
Gemfile編集
gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
Gemインストール
$ bundle install
カラム追加
「User」モデルに下記の2つのカラムを追加
- 「uid:string」
- 「provider:string」
$ rails g migration AddColumnsToUsers uid:string provider:string
マイグレーション実行
$ rails db:migrate
Devise設定
Devise.setup do |config|
# ...
config.omniauth :facebook,
Settings.facebook[:facebook_api_key],
Settings.facebook[:facebook_api_secret],
scope: 'email',
info_fields: 'email,name'
config.omniauth :twitter,
Settings.twitter[:twitter_api_key],
Settings.twitter[:twitter_api_secret]
# ...
end
Userモデルにモジュールとfindメソッドを追加
- 「:omniauthable」のモジュールを追記
- findメソッドを追記
# ・・・
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :trackable, :confirmable,
:omniauthable, omniauth_providers: [:facebook, :twitter]
def self.from_omniauth(auth)
where(uid: auth.uid).first
end
def self.new_with_session(_, session)
super.tap do |user|
if (data = session['devise.omniauth_data'])
user.email = data['email'] if user.email.blank?
user.provider = data['provider'] if data['provider'] && user.provider.blank?
user.uid = data['uid'] if data['uid'] && user.uid.blank?
user.skip_confirmation!
end
end
end
# ・・・
Userコントローラにコールバック処理を実装
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# Facebook上でメール使用を許可しているかの分岐
if request.env['omniauth.auth'].info.email.blank?
redirect_to '/users/auth/facebook?auth_type=rerequest&scope=email'
end
# User.from_omniauthはModel側で実装
user = User.from_omniauth(request.env['omniauth.auth'])
# すでにuserが登録済みかの判定
if user
# 登録済みならログイン
sign_in_and_redirect user, event: :authentication
set_flash_message(:notice, :success, kind: "Facebook") if is_navigational_format?
else
# 新規登録用にセッションに必要情報を格納
if (data = request.env['omniauth.auth'])
session['devise.omniauth_data'] = {
email: data['info']['email'],
provider: data['provider'],
uid: data['uid']
}
end
redirect_to new_user_registration_url
end
end
def failure
redirect_to root_path
end
def twitter
user = User.from_omniauth(request.env['omniauth.auth'])
if user
sign_in_and_redirect user, event: :authentication
set_flash_message(:notice, :success, kind: "Twitter") if is_navigational_format?
else
if (data = request.env['omniauth.auth'])
session['devise.omniauth_data'] = {
email: data['info']['email'],
provider: data['provider'],
uid: data['uid']
}
end
redirect_to new_user_registration_url
end
end
end
「routes.rb」に追記
Rails.application.routes.draw do
devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }
# ...
end
omniauth_dataの削除
class Users::SessionsController < Devise::SessionsController
def new
session.delete('devise.omniauth_data')
super
end
end
ログインリンク追加
<%= link_to "Facebookでログイン", user_facebook_omniauth_authorize_path %>
<%= link_to "Twitterでログイン", user_twitter_omniauth_authorize_path %>
#参考
【Devise+OmniAuthでユーザ認証を実装する手順 - Qiita】
https://qiita.com/kami_zh/items/94aec2d94a2b4e9a1d0b
【Devise+OmniAuthを用いてログインするためのメモ - Qiita】
https://qiita.com/minakawa-daiki/items/e54ab46b382a19dcbbf4