Posted at

OmniAuthTwitterでコンシューマーキーを複数使う

More than 3 years have passed since last update.

※ 技術的に可能か調べただけなので、やる場合は自己責任でお願いします。

TwitterAPIのリクエスト制限を回避するために色々考えまして、タスクやユーザーごとにコンシューマーキーを切り替えられたらいいなと思いました。


omniauth-twitterについて

omniauth-twitterは、omniauthと併用することにより、Twitter認証を簡単にしてくれるgemです。コンシューマーキー等の設定は、以下のように書きます。

Rails.application.config.middleware.use OmniAuth::Builder do

provider :twitter, "consumer_key", "consumer_secret_key"
end

こうすることで/auth/twitterにアクセスするとtwitter認証が走り、/auth/twitter/callbackにリダイレクトされごにょごにょと色々できるようになります。とても便利ですよね。


API制限の回避方法

TwitterAPIには、リクエスト数に制限があります。

作ったサービスのユーザー数が増えた時や、(APIリクエストの回数的な意味で)重い処理が走る場合にすぐに制限がかかってしまいます。そこで、 1アプリケーション内で複数のコンシューマーキーを利用することができないかと考えました。


request_path, callback_path の落とし穴

omniauth-twitterには、request_pathcallback_pathなるものがあり、

<request_path>にアクセスすると、<callback_path>にリダイレクトされ、ごにょごにょできるようになるはず…なのですが、どうやらうまく動いてくれないようで、色んな方がこれに悩んでいました。


解決方法


path_prefixを使い振り分ける

path_prefixを使うと、/auth/twitterとなっていた/authの部分を他のパスに置き換えることができます。 例えば、path_prefix: "/hogehoge"と設定すると、/hogehoge/twitterにアクセスするとTwitter認証が走り、リダイレクト先が/hogehoge/twitter/callbackになります。これを用いて、どのコンシューマーキーでTwitter認証したかをルーティングパラメーターで判断し、Userモデルにそれを判別させるテーブルを用意してあげることで複数のコンシューマーキーをアプリ内で利用することが可能になりました。以下はその設定例になります。


config/initializers/omniauth.rb

Rails.application.config.middleware.use OmniAuth::Builder do

provider :twitter, Settings.twitter.alpha_consumer_key, Settings.twitter.alpha_consumer_secret_key, path_prefix: '/alpha'
provider :twitter, Settings.twitter.beta_consumer_key, Settings.twitter.beta_consumer_secret_key, path_prefix: '/beta'
provider :twitter, Settings.twitter.gamma_consumer_key, Settings.twitter.gamma_consumer_secret_key, path_prefix: '/gamma'
end


routes.rb

Rails.application.routes.draw do

get '/:type/:provider/callback', :to => 'sessions#callback'
post '/:type/:provider/callback', :to => 'sessions#callback'
# 省略
end


sessions_controller.rb

Class SessionsController < ApplicationController

skip_before_action :login_required, only: [:callback, :sign_in, :check]

def callback
auth = request.env['omniauth.auth']
user = User.find_by_provider_and_uid(auth['provider'], auth['uid']) || User.create_with_omniauth(auth)
user.update(api_type: params[:type])
redirect_to user_path(user.screen_name)
end

#省略
end


以上です。どなたかのお役に立てると幸いです。