No day younger than today

RubyとかRailsとか蒙古タンメンとか

【Rails】自作アプリで Google ログインができなくなった

こんにちは、 ふーが( @fugakkbn ) です。
ブログを書くのはだいぶお久しぶりになってしまいました。
3月からWEB エンジニアとして働いており、元気に楽しくすごしています。

最近、就職前に公開した自作アプリをよくいじっています。
そんな中で、ちゃんと動いていたはずの「Google ログイン」が動かなくなっていることに気が付きました。

Google ログインボタンをクリックすると Not found. Authentication passthru. と表示されてログインできなくなっていたのです。

ログインしようとするとこんな画面になる

結論

さきに結論を書いてしまうと、「rails-ujs を使わなくなったことで link_to メソッドで post リクエストができなくなったから」です。
Google ログイン用リンクの link_tobutton_to に置き換えることで直りました。

これだけだと味気ないので、原因特定に至るまでに確認したことも書いておきます。

確認したこと

Google oAuth の仕様変更

最初に疑ったのはこれでした。なにかしらの仕様変更があったことでログインできなくなってしまったのかな?と。

しかし調べてみても、それらしき情報は見当たりませんでした。
仕様変更があったら影響を受けるサービスは多いでしょうから、その手の記事や公式のアナウンスがないならこの線はないかな、と思いました。

gem のバージョン影響

Google ログインを実現するのに、いくつか gem を使用しています。

使っている gem のバージョンが古くなってしまったのかな?と思い、それぞれの最新バージョンを確認することにしました。
古くなっていれば、アップグレードすることで解消するかも。

しかし、いずれも最新版を使用していました。
いずれも公開当初から最新版を使っていたことになるので、バージョンによる影響ではなさそうです。

自分のブログを見直す

他の原因を考えましたが、特に思い当たるものもなく。。。「そういえば、実装当時に実装方法に関するブログを書いたな」と思い出し、何かしらのヒントがないか見てみることにしました。

fuga-ch85.hatenablog.com

「過去の自分、一生懸命書いたんやな〜」と謎の悦に浸っていると、こんな記述がありました。

認証リンクへのリクエストメソッドはPOSTである必要があります。 button_toやlink_to ..., method: :postを使わないと動かないので注意してください。

自分で書いておきながらこのことはすっかり忘れていました。
まぁもともと POST メソッドで実装してるなら変わってるわけないだろうと思いつつ、念のためリクエストの内容を確認してみることにしました。

リクエスト内容を確認する

GET になってるやないかい!!!

というわけで、ここが原因っぽいことがわかりました。
Google ログインボタンをクリックしたときのリクエストメソッドが POST になるようにしてあげれば、直りそうです。

なぜ POST リクエストじゃなくなってしまったのか

実装時はブログに書くくらいですし、POST リクエストになるように実装しているはずです。
該当のコードを見たところ、確かに method: :post の記述がありました。

= link_to omniauth_authorize_path(resource_name, provider), method: :post, class: 'button max mt-4'
  img.icon src='/g-logo.png'
    span Googleアカウントでログイン

ではなぜ POST リクエストをするように実装したはずのリンクが、GET リクエストをするようになってしまったのでしょうか。

実は少し前に、Rails 7 にバージョンアップし rails-ujs を使わないようにする Pull Request をマージしていました。
上のコードが動かなくなったのは、まさにこれが原因だったようです。

Rails 7 から標準になった turbo-rails を使って link_to の書き方を Turbo 仕様にすれば動くのですが、Devise を使っている都合上( Devise はまだ Turbo に対応していない)、Turbo を使えません。*1

そういうわけで、 link_to の代わりに button_to を使うように変更して、 method: :post がちゃんと動くようになりました。

= button_to omniauth_authorize_path(resource_name, provider), method: :post, class: 'button max mt-4'
  img.icon src='/g-logo.png'
    span Googleアカウントでログイン

めでたしめでたし。

*1:厳密にいえば使えるのですが、Turbo 対応のために本来修正の必要がない View ファイルやコントローラーをいじるのは本意でないのでやっていません(ただめんどくさいだけw)。