Jex’s Note

Rails Oauth

FB Oauth

如果使用 Devise,請不要用下列的方法,請到這篇搜尋 oauth-facebook

申請 FB APP

1) Developers

2) Add a New App 選擇 Website (網站)

3) 建立 App -> 輸入一個 Name -> 按步驟 -> Create a New App ID

4) 建立成功, 下面有個欄位輸入 Domain : http://test.jex.tw:3000/

如果沒有 domain 可以暫時用 ngrok,但注意!FB 登入時要用 http://e2191881.ngrok.io/ 而不是 http://127.0.0.1:3000/

5) 右上角大頭像的 My Apps 選剛剛建立的 App

6) 將 App ID 及 App Secret Copy 貼到安裝完 omniauth 的設定檔 config/initializers/omniauth.rb

如果日後要換 domain 一樣在 App Dashboard 頁面, 在 App ID 下面那塊, 選擇 Choose a Platform -> WWW -> 就可以改 domain 了

Install

Gemfile

gem 'omniauth', '~> 1.3.1'
gem 'omniauth-facebook', '~> 3.0.0'

安裝完重啟動 rails

新增 User model

rails g model User provider uid name oauth_token oauth_expires_at:datetime

或直接建立

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :provider
      t.string :uid
      t.string :name
      t.string :oauth_token
      t.datetime :oauth_expires_at

      t.timestamps null: false
    end
  end
end

app/models/user.rb

def self.from_omniauth(auth)
  where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
    user.provider = auth.provider
    user.uid = auth.uid
    user.name = auth.info.name
    user.oauth_token = auth.credentials.token
    user.oauth_expires_at = Time.at(auth.credentials.expires_at)
    user.save!
  end
end

寫入後資料如下

:id => 1,
:provider => "facebook",
:uid => "860********7924",
:name => "Jex Lin",
:oauth_token => "CAAF5japY********************n7hjii",
:oauth_expires_at => Sat, 10 Oct 2015 14:26:09 UTC +00:00,

新增 Sessions Controller

app/controllers/application_controller.rb

private
def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user

app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  def create
    user = User.from_omniauth(env["omniauth.auth"])
    session[:user_id] = user.id
    redirect_to root_url
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_url
  end
end

新增 routes

config/routes

match 'auth/:provider/callback', to: 'sessions#create', via: [:get, :post]
match 'auth/failure', to: redirect('/'), via: [:get, :post]
match 'signout', to: 'sessions#destroy', as: 'signout', via: [:get, :post]

手動建立 Omniauth initializer

config/initializers/omniauth.rb

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, '41512******2503', '1791f7944e*********7ebaa65989414'
end

登入 / 登出

app/views/welcome/index.html.erb

<div id="user-widget">
  <% if current_user %>
    <%= link_to "Sign out", signout_path, id: "sign_out" %>
  <% else %>
    <%= link_to "Sign in with Facebook", "/auth/facebook", id: "sign_in" %>
  <% end %>
</div>

(選項, 可不加) JS :

$(document).ready(function () {

    $('body').prepend('<div id="fb-root"></div>')

      $.ajax
        url: "#{window.location.protocol}//connect.facebook.net/en_US/all.js"
        dataType: 'script'
        cache: true


    window.fbAsyncInit = ->
      FB.init(appId: 'YOUR-APP-ID', cookie: true)

      $('#sign_in').click (e) ->
        e.preventDefault()
        FB.login (response) ->
          window.location = '/auth/facebook/callback' if response.authResponse

      $('#sign_out').click (e) ->
        FB.getLoginStatus (response) ->
          FB.logout() if response.authResponse
        true
});

ref : https://coderwall.com/p/bsfitw/ruby-on-rails-4-authentication-with-facebook-and-omniauth

Comments