RailsでFacebookログインを実装する

Shunsuke Sawada

これを実装する度に毎回Railscastsを確認しているので、いい加減自分でまとめておきます。

準備

omniauth-facebook

https://developers.facebook.com でアプリをつくる。
赤い四角の所は必須だと思います。+Add Platform ウェブサイトの入力欄もつくります。
facebook-app

  

Gemfile

1
2
3
gem 'omniauth-facebook'

  
config/initializers/omniauth.rb

ruby
1
2
3
4
5
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET']
end

  
FACEBOOK_KEYとFACEBOOK_SECRETは環境変数なので、
CentOSとかの場合は ~/.bash_profile なんかを編集、
herokuの場合はheroku config:set FACEBOOK_KEY=0123456789などとして設定しておいてください。

  

ルーティングの設定

failureは、なんらかの原因でログインが失敗した時に、表示させるページ。
ログインボタンのリンクは/auth/facebookです。

ruby
1
2
3
4
get '/auth/:provider/callback',    to: 'users#create',       as: :auth_callback
get '/auth/failure',               to: 'users#auth_failure', as: :auth_failure

  

コントローラー

Facebookから返ってくる情報を使って、ユーザーを作成したり、ログインさせたりします。
ログインの度に、iconや名前を更新したいので、@user.saveしています。
sign_inメソッドについては説明しませんが、current_userに該当のuserを代入しているだけです。

  
from_omniauthメソッドやcontext: :facebook_loginについてはモデルにて。
env['omniauth.auth']にいろいろ情報が入っているので、引数として渡しています。

controllers/users_controller.rb

ruby
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    def create

        if env['omniauth.auth'].present?
            # Facebookログイン
            @user  = User.from_omniauth(env['omniauth.auth'])
            result = @user.save(context: :facebook_login)
            fb       = "Facebook"
        else
            # 通常サインアップ
            @user  = User.new(strong_params)
            result = @user.save
            fb       = ""
        end
        if result
            sign_in @user
            flash[:success] = "#{fb}ログインしました。" 
            redirect_to @user
        else
            if fb.present?
                redirect_to auth_failure_path
            else
                render 'new'
            end
        end
    end

  

モデル

同じメールアドレスが見つかれば、そのユーザーとしてログイン。
そうでなければ、新しくユーザーを作成します。

Facebookログインでは、パスワードが必要ありませんので、パスワードのバリデーションを無効にしています。
on: :facebook_loginを加えておいて、コントローラーでセーブする際に@user.save(context: :facebook_login)としています。

models/user.rb

ruby
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    validates :password, presence: false, on: :facebook_login

    def self.from_omniauth(auth)
        # emailの提供は必須とする
        user = User.where('email = ?', auth.info.email).first
      if user.blank?
        user = User.new
      end
    user.uid   = auth.uid
    user.name  = auth.info.name
    user.email = auth.info.email
    user.icon  = auth.info.image
    user.oauth_token      = auth.credentials.token
    user.oauth_expires_at = Time.at(auth.credentials.expires_at)
    user
    end

  
/auth/facebook を叩けば、Facebookのダイアログが表示されるはず。

以上か、な…?
なんかまとめ忘れている気もしなくもないが。。

20
Shunsuke Sawada