Rails 6 + Devise 串第三方登入 google, fb
04 Jun 2020紀錄串接第三方登入的實作過程
發現網路上有如此豐富的資源,還有許多好用的套件,真是一件十分幸福的事非常適合懶人!
step 1.
In Gemfile
gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'
gem 'figaro'
bundle install
啟動figaro:bundle exec figaro install
此時會長出config/application.yml,並將檔案加入.gitignore
figaro為設定環境變數的管理套件:figaro
step 2.
在 application.yml,放置fb & google申請api的client_id & client_secret client_id & client_secret可在官網先申請好
development:
google_client_id: "your_id"
google_client_secret: "your_secret"
fb_client_id: "your_id"
fb_client_secret: "your_secret"
step 3.
在 config/initializers/devise.rb的Devise.setup do |config|
….end
之間加入下列:
config.omniauth :facebook, ENV['fb_client_id'], ENV['fb_client_secret'], scope: "public_profile,email", info_fields: "email,name"
config.omniauth :google_oauth2, ENV['google_client_id'], ENV['google_client_secret'],{access_type: "offline", approval_prompt: ""}
如此一來就設定完環境變數。
step 4.
建立新的欄位給 user 儲存第三方的 id
rails g migration add_omniauth_to_users provider:string uid:string
rails db:migrate
step 5.
class User < ApplicationRecord
# 定義omniauth要允許哪些第三方
devise :omniauthable, omniauth_providers: [:facebook, :google_oauth2]
# 定義類別方法,找到user的話就登入,找不到就建立user
def self.create_from_provider_data(provider_data)
where(provider: provider_data.provider, uid: provider_data.uid).first_or_create do |user|
user.email = provider_data.info.email
user.password = Devise.friendly_token[0, 20]
end
end
end
step 6.
# 新增omniauth_callbalck路徑,去找omniauth_callbacks_controller
Rails.application.routes.draw do
devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }
end
step 7.
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
@user = User.create_from_provider_data(request.env["omniauth.auth"])
if @user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google"
sign_in_and_redirect @user, :event => :authentication
else
session["devise.google_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def facebook
@user = User.create_from_provider_data(request.env["omniauth.auth"])
if @user.persisted?
sign_in_and_redirect @user, event: :authentication
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
參考資料: