0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WordPressで認証導線を作ったら ERR_TOO_MANY_REDIRECTS になった話(if切り分け+404返却で解決)

0
Last updated at Posted at 2025-12-17

WordPressで認証導線を作ったら ERR_TOO_MANY_REDIRECTS になった話(if切り分け+404返却で解決)

他の言語のログイン画面より、トークンを受け取ったらwordpress側のフロントエンドを見せる仕組み
wordpress自体のログイン機能は使わない。
リダイレクト多くてエラーを繰り返してしまいます。

外部のログイン画面(アプリ/別実装)から ?token=xxxx を付けて WordPress に遷移し、以後は Cookie(__session)を鍵にして閲覧可否を判定する仕組みを作っていました。
ところが実装途中で ERR_TOO_MANY_REDIRECTS(リダイレクトが多すぎる) を踏みました。

結論としては、

  • **if文の切り分け(処理順の整理)**で無限ループを止める
  • 未認証時は「別URLにリダイレクト」ではなく、WordPress側で 404 を返す(= その場で404テンプレを表示)で安定しました。
    #/webview のような hash はサーバー側に届かないので、WordPressからは常に /login/ にしか見えない、という落とし穴もありました )

なぜ無限リダイレクトになるのか

典型的にはこういう流れになります。

  1. 初回だけ /?token=xxxx でアクセス
  2. WordPress側が「未認証」判定 → /login/ にリダイレクト
  3. リダイレクト先には token が付かない(ヘッダーも付かない)ので、また未認証
  4. /login/ にまたリダイレクト…を繰り返し、ERR_TOO_MANY_REDIRECTS

つまり **「token を cookie に変換する前に redirect してしまっている」**のが致命傷でした


解決方針:ifの切り分け(処理順を固定)

  1. token が来たら最優先で cookie 化(この前に未認証リダイレクトを書かない)
  2. /login 等は 認証リダイレクト対象から除外(ループ防止)
  3. 以後の認証判定は cookie だけ

さらに安定させる:未認証時は「リダイレクト」ではなく「404を返す」

今回の最終判断がここでした。

未認証ユーザーを「ログイン画面へ飛ばす」運用にすると、

  • 設計や環境によっては /login/ 側でまた判定が走る
  • WebView等で Cookie が保持されないケースだと、永遠に未認証のまま

となって、再発しやすいです(Cookie保持問題が絡むと特に)

そこで、未認証で見せたくないページは “存在しない扱い(404)” にする方針にしました。
リダイレクトではなく その場で 404 ヘッダー+404テンプレを返すので、ループの余地が減ります。


実装例(そのまま使える)

is_page('mypage') の部分は、保護したいページ条件に合わせて変更してください。

<?php
// functions.php など
add_action('template_redirect', function () {
  $uri = $_SERVER['REQUEST_URI'] ?? '';

  // 404 を返す共通処理(今回使ったやつ)
  $return_404 = function () {
    status_header(404);
    nocache_headers();
    include get_404_template();
    exit;
  };

  /*
   * 1) token が来たら最優先で cookie に変換
   *    (ここより前に「未認証なら〜へリダイレクト」を書かない)
   */
  if (!empty($_GET['token']) && empty($_COOKIE['__session'])) {
    setcookie('__session', (string) $_GET['token'], [
      'expires'  => time() + 60 * 60 * 24 * 7,
      'path'     => '/',
      'secure'   => is_ssl(),
      'httponly' => true,
      'samesite' => 'Lax',
    ]);

    // token をURLから消してクリーンに
    wp_safe_redirect(remove_query_arg('token'));
    exit;
  }

  /*
   * 2) /login は除外(ここが無いとループしやすい)
   *    ※ #/webview などの hash はサーバーに届かないので URL文字列で判定する
   */
  if (preg_match('~^/login/?($|\?)~', $uri)) {
    return;
  }

  /*
   * 3) ここから cookie で認証判定
   *    未認証なら「リダイレクト」ではなく「404を返す」
   */
  if (is_page('mypage')) {
    if (empty($_COOKIE['__session'])) {
      $return_404();
    }
  }
});

この構成にして良かった点

  • リダイレクトループが起きにくい(未認証時に別URLへ飛ばさない)
  • 「保護ページの存在」を未認証ユーザーに見せない(404扱い)
  • token は初回だけ消費して cookie に変換し、以後は cookie だけで判定できる

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?