deviseを複数のモデルでのTwitter認証を実装しようとすると、うまくいかない。
自分は開発中のuserモデルとartistモデルがあるケースでつまったのでまとめていきます。
twitterapiの設定
Twitterのdeveloperアカウントは2018年の秋頃からしようが変更になり、英語でサービスがどのように使われるかを明示しなければならなくなりました。
https://qiita.com/tdkn/items/521686c240b0c5bc6207
承認されない時は、twitter社からメールが届き、いくつかの質問がされます。自分は2回ほどのメールのやり取りを経て、やっとアカウントが承認されました。(サービスをもっと具体的に教えろなど...)
APIKEYを設定してdeviseとomniauthの設定
gem 'devise'
gem 'omniauth-twitter'
を入れて、
下の記事のようにdeviseの設定とomniauthの設定をします
https://qiita.com/daigou26/items/d84e64af775a3054e950
複数モデルに適用させる
問題はここからです。omniauth+deviseだと複数モデルの時に適用されないのです。
実は公式のドキュメントに、
現時点では、DeviseのOmniauthableモジュールはそのままでは1つのモデルでしか利用できません。しかしご安心ください。
OmniauthableはOmniAuthの単純なラッパーにすぎないので、方法はあります。
と、記載があります。
手順にそって、複数modelにおいてもsns認証ができるようにしていきましょう。
1. deviseにおいてomniauthを使わない。
まず、userとartistのcontrollerにある
devise :omniauthable
を削除します。
2.ルーティング作成
また、routes.rb
に、
get "/auth/twitter/callback" => "omniauth_callbacks#twitter"
get '/auth/another/twitter/callback' => 'anothers#twitter'
と記述し、deviseを使わずにそれぞれのルーティングを作成します。
3. controller設定
次にcontrollers/omniauth_callbacks.rb
というコントローラーを作成し、
次にcontrollers/omniauth_callbacks__controller.rb
というコントローラーを作成し、
class OmniauthCallbacksController < ApplicationController
def twitter
callback_from :twitter
end
def failure
@notice = "failure"
redirect_to events_path, notice: 'failure'
end
private
def callback_from(provider)
provider = provider.to_s
@user = User.find_for_oauth(request.env['omniauth.auth'])
if @user.persisted?
print("persisted true")
@notice = "persisted true"
flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
sign_in_and_redirect @user, event: :authentication
else
print("persisted false")
session["devise.#{provider}_data"] = request.env['omniauth.auth']
@notice = "user is not persisted."
redirect_to root_path, notice: 'user is not persisted.'
end
end
end
と記述します。
次に別のanothers_controller.rb
というコントローラーを作成し、
class AnothersController < ApplicationController
def twitter
callback_from :twitter
end
def failure
@notice = "failure"
redirect_to events_path, notice: 'failure'
end
private
def callback_from(provider)
provider = provider.to_s
@artist = Artist.find_for_oauth2(request.env['omniauth.auth'])
if @artist.persisted?
print("persisted true")
@notice = "persisted true"
flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
sign_in_and_redirect @artist, event: :authentication
else
print("persisted false")
session["devise.#{provider}_data"] = request.env['omniauth.auth']
@notice = "user is not persisted."
redirect_to root_path, notice: 'user is not persisted.'
end
end
end
とし、別のモデルからの設定をします。
4.プロバイダ作成
二つのルーティングができるようにプロバイダを変更します。
OmniAuth.config.full_host = "https://hogehoge.com"
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'],info_fields:"nickname, image", request_path: '/auth/twitter', callback_path: '/auth/twitter/callback'
provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'],info_fields:"nickname, image", request_path: '/auth/another/twitter', callback_path: '/auth/another/twitter/callback'
end
5.viewの設定
これで、
<%= link_to 'twitterでログイン', '/auth/twitter', :id => "twitter" %>
<%= link_to 'twitterでログイン', '/auth/another/twitter', :id => "twitter" %>
と記述すると、無事ルーティングされます。
参考記事