imotanの気になる木

21歳、大学4年(未就活)の意識高い系の大学生の日記的ブロクです。

facebook認証

ライブラリのインストール

gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-twitter'

カラムの追加 OmniAuthではuid(一意のID)とprovider(FacebookTwitterなど)をカラムとして利用する。

$ rails g migration AddColumnsToUsers uid:string provider:string

Deviseの設定

config/initializers/devise.rb
Devise.setup do |config|
  # ...

  config.omniauth :facebook, 'App ID', 'App Secret'
  config.omniauth :twitter, 'API key', 'API secret'
end

Userモデルにモジュールを追加

devise :database_authenticatable, :registerable,
       :recoverable, :rememberable, :trackable, :validatable, :omniauthable

Userモデルにfindメソッドを実装 uidとproviderの組み合わせは一意であり、これによりユーザを取得する。 レコードに存在しない場合は作成する。

app/models/user.rb
class User < ActiveRecord::Base
  # ...

  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
  end

  private

  def self.dummy_email(auth)
    "#{auth.uid}-#{auth.provider}@example.com"
  end
end

メールアドレスでの認証も実装している場合、OAuthでの認証時もメールアドレスを保存する必要がある。 ここでは、uidとproviderの組み合わせが一意なことを利用して、self.dummy_emailのように生成している。

Userコントローラにコールバック処理を実装(わからん)

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    callback_from :facebook
  end

  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

ルーティング処理 以下のように、OAuthのコールバック用のルーティングを設定する。

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

# ... end

認証用リンクを追加 以下によりリンクが生成される。 これをビューの任意の位置に記述する。

user_omniauth_authorize_path(:facebook) user_omniauth_authorize_path(:twitter)