💻

【Rails 7】ActionController::Redirecting::UnsafeRedirectErrorが出た時の対応

2024/08/11に公開

はじめに

こんにちは。現在プログラミングスクールでRuby on Railsを学習しているmockeyです。
卒業制作にて海外旅行初心者向けの準備アプリを作成しており、その中でユーザーに公式LINEからリマインド通知を送る機能を実装しています。
実装中に表題のエラーが起こったため、備忘録としてこの記事で取り扱うことにしました。
何か少しでも参考になることがあれば幸いです。

前提

この記事ではエラーの内容に焦点を当てているので、LINE通知機能についての説明は割愛いたします。
ご了承くださいませ。

記事のゴール

  • ActionController::Redirecting::UnsafeRedirectErrorがどういうエラーなのかを知る
  • ActionController::Redirecting::UnsafeRedirectErrorが出た時の対処法が分かる

環境

  • ruby 3.2.3
  • rails 7.1.3.4

エラーの発生箇所

line_auth_controllerについて
LINEのユーザーとアプリケーションユーザーの紐付け処理のためのコントローラー。
LINEログインを通じて取得したユーザーIDをアプリのcurrent_userに紐付けする。

エラー発生時の該当コード

app/controllers/line_auth_controller.rb
class LineAuthController < ApplicationController
  def link
    redirect_to line_login_url
  end

~~~~~~~~~省略~~~~~~~~~~~~~

  private

  def line_login_url #LINE認証ページのURLを生成
    client_id = ENV['LINE_LOGIN_CHANNEL_ID']
    redirect_uri = line_auth_callback_url
    state = SecureRandom.hex(10) #CSRF対策のためのstateパラメータ
    scope = "profile openid" #プロフィール情報を取得するためのスコープ
    bot_prompt = "aggressive" #LINEログイン画面でのユーザーへのプロンプト表示

    "https://access.line.me/oauth2/v2.1/authorize?response_type=code&client_id=#{client_id}&redirect_uri=#{redirect_uri}&state=#{state}&scope=#{scope}&bot_prompt=#{bot_prompt}"
  end

エラー内容

Image from Gyazo

デベロッパーツールで確認できたエラー
Image from Gyazo

UnsafeRedirectErrorという名前からして何やら不安全であることが読み取れるエラーですね。

エラーの調査

ActionController::Redirecting::UnsafeRedirectErrorについて調べたところ、以下の内容であることが判明しました。

Railsガイドによると、Rails 7.0以降では外部ホストへのリダイレクト(オープンリダイレクト)がデフォルトで制限されています。

オープンリダイレクトのリスク

オープンリダイレクト脆弱性とは、ウェブサイトが適切にチェックされていない入力をもとに、ユーザーを別の悪質なサイトに誘導してしまう問題です。
この脆弱性を悪用することで、攻撃者はユーザーを騙して、自分の情報を攻撃者に提供させたり、フィッシング詐欺に巻き込んだりすることができます。例えば、信頼できるサイトと見せかけたリンクをクリックさせ、実際には危険なサイトに飛ばしてしまうなど。
これにより、ユーザーは自分が安全だと思っている情報を、知らずに攻撃者に渡してしまう危険があります。

config.action_controller.raise_on_open_redirectsは、Railsの設定の一つ。
アプリケーションが外部のURLにリダイレクトされるのを防ぐために使われます。

バージョン デフォルト値
オリジナル false
7.0以降 true
  • Rails 7以降はデフォルトでtrueに設定されている
    つまり外部リダイレクトが自動的に防がれるので、外部ホストを含むURLがredirect_toに渡されるとActionController::Redirecting::UnsafeRedirectErrorが発生します。

今回の場合、line_login_urlメソッドが生成しているURLは、LINEの認証ページへの外部URLです。
具体的には、https://access.line.me/oauth2/v2.1/authorize~~ というURLが外部ホストにあたるので、Railsの設定によってリダイレクト時にエラーが発生しました。

  • 500エラーについてはこちらの記事で詳しく書いてありましたので割愛します。

解決方法

Railsガイドによると、外部ホストを含むURLを許可する際はredirect_toの呼び出しにallow_other_host: trueオプションを追加する必要があります。

修正後のコード

app/controllers/line_auth_controller.rb
def link
    redirect_to line_login_url, allow_other_host: true #追加
end

終わりに

今回は外部ホストを含むURLをリダイレクトした際のエラー対応について紹介しました。
Google認証を実装した際はこの様なエラーがなかったのですが、GPTによると以下の様な回答がありました。しかし、参考文献が見つけられていないので、引き続き調査しようと思います。

よく使われる認証サービス(例: Google、Facebook)は、通常、ホワイトリストに追加されており、これらへのリダイレクトは問題なく許可されることが多い

今回もご覧いただきありがとうございました。

参考

Discussion