Liz's Blog

GemGem大亂鬥#7:Facebook驗證登入失敗?

| Comments

之前做的網站Facebook驗證登入突然不能使用了,所以來記錄一下怎麼修復及安裝omniauth-facebook的過程,參考來源為OmniAuthERROR — omniauth: (facebook) Authentication failure

【申請App】
1.到臉書Developer申請一個new app
2.點選Add a New App。
3.輸入Display Name。
4.點選Facebook Login (Set Up)。
5.點選Web。
6.輸入Site URL。
7.中間的設定可以都先跳過,選擇左側選單的Dashboard,取得app id和app secret。
8.最後app上線前,記得App Review把Make app public的按鈕打開即可。

【使用heroku的話,可以把帳密藏到heroku上】
1.終端機:heroku config:set app_id=xxxxxxx
2.終端機:heroku config:set app_secret=xxxxxxx

【安裝omniauth-facebook】
1.

Gemfile
gem 'omniauth-facebook', '~> 4.0'

2.終端機:rails g migration AddOmniauthToUsers provider:string uid:string
3.終端機:rake db:migrate
4.因為facebook的API變動蠻快的,所以最好依照當初申請app的版本來做修正(我申請時的時候是v2.10)。

config/initializers/devise.rb
config.omniauth :facebook, ENV['app_id'], ENV['app_secret'], scope: 'email',
    client_options: {
      site: 'https://graph.facebook.com/v2.10',
      authorize_url: "https://www.facebook.com/v2.10/dialog/oauth"
    }

5.讓User可以被omniauthable。

app/models/user.rb
....
devise :omniauthable, :omniauth_providers => [:facebook]
....

6.在你想要顯示Facebook登入的View,加入以下路徑。

app/views/common/_navbar.html.erb
....
<li><%= link_to "Sign in with Facebook", user_facebook_omniauth_authorize_path %></li>
....

7.加入callback。

config/routes.rb
....
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
....

8.新增app/controllers/users/omniauth_callbacks_controller.rb檔案。

app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated
      set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end
end

9.定義from_omniauth。

app/models/user.rb
....
def self.from_omniauth(auth)
  where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
    user.email = auth.info.email
    user.password = Devise.friendly_token[0,20]
  end
end

Comments

comments powered by Disqus