Google OAuth 2 redirect_uri_mismatchになる

rails4でomniauth-google-oauth2を使ってソーシャルログイン機能を実装していたところ、以下のエラーでコールバック処理が実行されない。

I, [2016-01-07T20:31:38.193280 #1009]  INFO -- omniauth: (google) Request phase initiated.
Started GET "/auth/google/callback?state=xxxx&code=xxxx" for ::1 at 2016-01-07 20:31:42 +0900
I, [2016-01-07T20:31:42.931819 #1009]  INFO -- omniauth: (google) Callback phase initiated.
E, [2016-01-07T20:31:43.025677 #1009] ERROR -- omniauth: (google) Authentication failure! invalid_credentials: OAuth2::Error, redirect_uri_mismatch: 
{
"error" : "redirect_uri_mismatch"
}

この時の設定内容は以下のとおり。他のプロバイダのログインも一緒に試していたので、google以外のものも含まれている。

Rails.application.config.middleware.use OmniAuth::Builder do
  [:twitter, :facebook, :github, :google].each do |prov|
    auth = Rails.application.secrets[prov]
    if :google == prov
      provider :google_oauth2, auth["omniauth_provider_key"], auth["omniauth_provider_secret"], {
          scope: "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/plus.me https://www.google.com/m8/feeds",
          name: prov,
          redirect_uri: "http://localhost:3000/auth/google/callback"
      }
    else
      provider prov, auth["omniauth_provider_key"], auth["omniauth_provider_secret"]
    end
  end
end

Google Developer Consoleでの設定は以下のとおりで、redirect_uriは一致している。

流れを追ってみると、どうもアクセストークンを要求するリクエストでrequest_uriパラメータの値が、Google Developer Consoleに登録しているものと異なっていることが起因しているようだった。では、この時のrequest_uriはというと以下のようになっている。

http://localhost:3000/auth/google/callback?state=a72ba65179bf12b10f34848eae9437ff59a4fbc1a9ebf12b&code=4/eMToVraxQlPFriO-FAQCab7cZyO2asVBe80__RA_vfU

色々と調べていたところ、以下のissuesに同じような報告があった。

github.com

どうやらgoogleの場合は、request_uriにこれらのクエリがあると上手くいかないようだ。このrequest_uiを生成しているのは以下の箇所っぽい。query_stringがある場合に上手くいかない。

# oatuth2.rb OmniAuth::Strategy#callback_url
def callback_url
  full_host + script_name + callback_path + query_string
end

上のissueでは、クエリrequest_uriの値をomniauthのsetup_phasesetupオプションを使って書き換えているようだった。issueのworkaroundを参考に以下のように書いてみたところ上手くいった。

Rails.application.config.middleware.use OmniAuth::Builder do
  [:twitter, :facebook, :github, :google].each do |prov|
    auth = Rails.application.secrets[prov]
    if :google == prov
      provider :google_oauth2, auth["omniauth_provider_key"], auth["omniauth_provider_secret"], {
          scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/plus.me https://www.google.com/m8/feeds',
          name: prov,
          # ここが該当箇所
          setup: (
          lambda do |env|
            env['omniauth.strategy'].options['token_params'] = {
                :redirect_uri => "http://localhost:3000/auth/google/callback"
            }
          end)
      }
    else
      provider prov, auth["omniauth_provider_key"], auth["omniauth_provider_secret"]
    end
  end
end

ちなみに僕の環境は以下のとおり。

  • omniauth-oauth2 (1.4.0)
  • omniauth-google-oauth2 (0.2.8)

参考リンク

byebyehaikikyou

日記やIT系関連のネタ、WordPressに関することなど様々な事柄を書き付けた雑記です。ITエンジニア経験があるのでプログラミングに関することなどが多いです。

シェアする

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

コメントする

Translate »