LoginSignup
22
20

More than 3 years have passed since last update.

【Rails】【Devise】twitter・Facebookログイン実装

Last updated at Posted at 2019-08-25

機能概要

「devise」のメールアドレスの新規会員登録機能に加えて、ソーシャルログイン機能も追加します。
具体的には、

ソーシャルログインリンクをクリック
 ▼ ▼ ▼
TwitterやFacebookに登録してあるメールアドレスを取得、パスワード入力で新規会員登録
 ▼ ▼ ▼
ソーシャルログインリンクをクリックすると、ログインができるようになる

という流れです。

前提

  • 会員登録に使用するモデルは「User」とします。
  • 「config」のgemを使用し、定数呼び出しを行える状態
  • 「devise」のメールアドレスの新規会員登録機能が実装されている状態

事前準備

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キーを呼び出せるようにする。

config/settings.local.yml
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編集

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設定

config/initializers/devise.rb
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メソッドを追記
app/models/user.rb

# ・・・

  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コントローラにコールバック処理を実装

app/controllers/users/omniauth_callbacks_controller.rb
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」に追記

config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }

  # ...
end

omniauth_dataの削除

app/controllers/sessions_controller.rb
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

22
20
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
20