OmniAuth + DeviceでTwitter, Facebook連携
1. 前提
・deviceでユーザー登録機能が実装されている
Rails 4.0.0.beta1でdevise - t-taira blog
・Twitter Developersに登録している
Twitter Developers
・Facebook Developersに登録している
Home - Facebook Developers
2. 設定関連
・GemFile
# twitter gem 'twitter' gem 'omniauth-twitter' # facebook gem 'fb_graph' gem 'omniauth-facebook' gem 'activerecord-session_store'
・config/routes
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } do delete '/users/disconnect/:provider', :to => 'users#disconnect_omniauth_provider', :as => 'disconnect_omniauth_provider' end resources :users
・config/initializers/devise.rb
# ココ追加 config.omniauth :twitter, 'CONSUMER_KEY', 'CONSUMER_SECRET', :display => 'popup' config.omniauth :facebook, 'APP_ID', 'APP_SECRET', :scope => 'manage_pages', :display => 'popup' DeviseController.class_eval do before_action :resource_params #, only: [:show, :edit, :update, :destroy] def resource_params unless params[resource_name].blank? params.require(resource_name).permit( # ココ追加 :twitter_id, :twitter_token, :twitter_secret, :facebook_id, :facebook_token, :facebook_secret, ・・・ ) end end end
3. Model
・app/models/user
class User < ActiveRecord::Base devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :omniauthable, :omniauth_providers => [:facebook, :twitter] # ココ追加 # 連携済みかどうか def connected?(provider) return eval("self.#{provider}_id.nil?") end # 以下、コールバックで呼ばれるメソッド追加 def self.find_for_facebook_oauth(access_token, signed_in_resource = nil) data = access_token.extra.raw_info User.where(:facebook_id => data.id).first end def self.find_for_twitter_oauth(access_token, signed_in_resource = nil) data = access_token User.where(:twitter_id => data.uid).first end def connect_with provider, authdata logger.info("AUTH: #{authdata.inspect}") case provider when :twitter self.twitter_id = authdata['uid'] self.twitter_token = authdata['credentials']['token'] self.twitter_secret = authdata['credentials']['secret'] when :facebook self.facebook_id = authdata['uid'] self.facebook_token = authdata['credentials']['token'] end save end end
4. Controller
・app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def facebook authorize :facebook do session["devise.facebook_data"] = request.env["omniauth.auth"] end end def twitter authorize :twitter do # http://stackoverflow.com/questions/7117200/devise-for-twitter-cookie-overflow-error session["devise.twitter_data"] = request.env["omniauth.auth"].except('extra') end end private def authorize provider @user = User.send "find_for_#{provider}_oauth", request.env["omniauth.auth"], current_user provider_name = provider.to_s.titleize # if current_user exists: # if @user is nil, connecting the account # if @user is not nil and not equal to current_user, show an error # else, see below: if current_user if @user.nil? current_user.connect_with provider, request.env['omniauth.auth'] flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => provider_name elsif @user != current_user # TODO: I18n flash[:error] = "That #{provider_name} account is already linked to a different user." else flash[:notice] = "Your account is already linked with the #{provider_name} account." end redirect_to edit_user_registration_path else if @user flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => provider.to_s.titleize sign_in_and_redirect @user, :event => :authentication else yield if block_given? redirect_to new_user_registration_url end end end end
・app/controllers/users_controller.rb
class UsersController < ApplicationController # 連携を解除するメソッド def disconnect_omniauth_provider provider = params[:provider] if Devise.omniauth_providers.include? provider.to_sym current_user.update_attributes( { "#{provider}_id" => nil, "#{provider}_token" => nil, "#{provider}_secret" => nil, } ) current_user.save flash[:success] = "Your account has been disconnected from #{provider.titleize}." end redirect_to edit_user_registration_path end ・・・ end
5. View
・app/views/layouts/application.html.erb
<div class="well sidebar-nav"> <p class="nav-header">SNS連携</p> <ul class="nav nav-tabs nav-stacked"> <% Devise.omniauth_providers.each do |provider| %> <% if current_user.connected?(provider) %> <li> <%= link_to image_tag("authbuttons/#{provider.to_s}_32.png") + " 認証する", user_omniauth_authorize_path(provider) %> </li> <% else %> <li> <%= link_to image_tag("authbuttons/#{provider.to_s}_32.png") + " 解除する", disconnect_omniauth_provider_path(provider), :method => :delete %> </li> <% end %> <% end %> </ul> </div>
6. 連携
Twitter.configure do |config| config.consumer_key = CONSUMER_KEY config.consumer_secret = CONSUMER_SECRET # oauth_token, oauth_token_secretは連携時に取得した値を利用 config.oauth_token = current_user.twitter_token config.oauth_token_secret = current_user.twitter_secret end twitter_client = Twitter::Client.new # ココはRailsアプリで登録したコンテンツにする twitter_client.update("hogehoge")
# facebook_tokenは連携時に取得した値を利用 me = FbGraph::User.me(current_user.facebook_token) # me.accounts[0]で最新のファンページを取得しているが... # 本当はファンページが複数ある場合は、指定したい page_access_token = me.accounts[0].access_token me = FbGraph::User.me(page_access_token) me.feed!( # # ココはRailsアプリで登録したコンテンツにする :message => 'hellow world!', :link => 'https://www.google.co.jp/')
Source: OmniAuth: Overview · plataformatec/devise Wiki · GitHub