paranitips

Never stop learning! がモットーのゆるふわエンジニアブログ

omniauthでfacebook, google+のSNS連携を実装する

作業環境

$ ruby --version
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin14.0]
$ rails --version
Rails 4.1.1

実装手順

必要なgemのインストール

まずはomniauthをgemでインストールします。

gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'
$ bundle

initializerの作成

config/initializer/omniauth.rbを作成します。

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, ENV['FB_APP_ID'], ENV['FB_SECRET']
  provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], name: :google
end

これで、/auth/:providerで各providerの認証ページにリダイレクトされるようになります。 google_oauth2name: :googleを設定しておくと、認証URLやコールバックURLでproviderがgoogleになるので便利です。

ENVの内容は各SNSでアプリやプロジェクトを作成して入手して書き換えてください。

モデルの作成

認証情報のモデルを作成します。

$ rails g model SocialProfile

migrationはここを参考に作っておけば大丈夫でしょう〜。

class SocialProfile < ActiveRecord::Base
    belongs_to :member
    store :other
    validates_uniqueness_of :uid, scope: :provider

    def set_values(omniauth)
        return if provider.to_s != omniauth['provider'].to_s || uid != omniauth['uid']
        credentials = omniauth['credentials']
        info = omniauth['info']

        self.access_token = credentials['token']
        self.access_secret = credentials['secret']
        self.credentials = credentials.to_json
        self.name = info['name']
        self.nickname = info['nickname']
        self.email = info['email']
        self.image_url = info['image']
        self.description = info['description'].try(:truncate, 255)
        case provider.to_s
        when 'google'
            self.nickname ||= info['email'].sub(/(.+)@gmail.com/, '\1')
        when 'facebook'
            self.url = info['urls']['Facebook']
        end

        self.set_values_by_raw_info(omniauth['extra']['raw_info'])
    end

    def set_values_by_raw_info(raw_info)
        case provider.to_s
        when 'google'
            self.url = raw_info['link']
        when 'facebook'
            # 特に追加する項目なし
        end

        self.raw_info = raw_info.to_json
    end
end

コントローラーの作成

SNSでの認証のコールバックを受けるコントローラーを作成します。

$ rails g controller sessions
class SessionsController < ApplicationController

  def callback
    omniauth = request.env['omniauth.auth']
    if omniauth.present?
      # 認証が成功したときの処理
      omniauth = request.env['omniauth.auth']
      if omniauth.present?
        profile = SocialProfile.find_or_initialize_by(provider: omniauth['provider'], uid: omniauth['uid'])
        profile.set_values(omniauth)
        # ...(ユーザ登録、ログイン等をしておく)
      end
    else
      # 認証情報がないときの処理
      # ...(エラーレンダリングとかしておく)
    end
  end

  def failure
    # 認証が失敗したときの処理(キャンセルを押された時とか)
    # ...(エラーレンダリングとかしておく)
  end
end

ルーティングの追加

...
get  '/auth/:provider/callback' => 'sessions#callback'
post '/auth/:provider/callback'  => 'sessions#callback'
get  '/auth/failure' => 'sessions#failure'
...

各providerの認証コールバックURLに/sessions/facebook/callback/sessions/google/callbackを設定すればOKです。

リンクの設置

<%= link_to 'Facebook連携', '/auth/facebook' %>
<%= link_to 'Google連携', '/auth/google' %>

以上です。omniauthかんたんですね!

参考