ログイン表示をアクセストークンcookieの有無からSSR導出すると期限切れで未ログイン表示に退行する
Next.js
JWT
認証
SSR
知識
判断
短命アクセストークン(AT) + 長命リフレッシュトークン(RT)構成で、ヘッダーなどのログイン状態表示をサーバーレンダリング時に「AT cookie が存在するか」から導出していると、AT の期限が切れて cookie が消えた時点から、RT がまだ有効でも UI が未ログイン表示に退行する。
退行が固定化する条件
次の3つの復元経路が同時に塞がっていると、表示は自己修復せず未ログインのまま残る。
- middleware などサーバー側の refresh が保護ルート(要ログイン画面)だけに限定され、公開ページのレンダリングでは走らない。
- サーバーレンダリングが AT cookie を直接読み、無ければ「未ログイン」をそのまま hydration でクライアントキャッシュに書き込む。
- クライアント側のフォーカス時再取得・定期再取得が無効で、401→refresh→リトライのインターセプタが発火する機会がない(表示は最初の描画のまま)。
症状の典型は「AT 期限経過後に公開ページを開く/リロードするとログインボタンに戻り、保護ルートを開いたり画面操作でクエリが再取得されると復活する」という間欠的な見え方になる。
判断
表示用のログイン状態は「AT の有無」ではなく「RT を含めた回復可能性」で導出する。具体的には次のいずれか(両方)で自己修復経路を確保する。
- 公開ページを含めて「AT なし かつ RT あり」ならサーバー側で refresh してから描画する。refresh 失敗時は未ログインとして素通しし、公開ページではログインへリダイレクトしない。
- ログイン状態を返すクエリだけフォーカス時再取得を有効にし、401 インターセプタの refresh 経路に乗せる。
落とし穴
RT ローテーション + 再利用検知がある場合、復元経路を増やすと並行 refresh の競合が増える。クライアント側のシングルフライト化に加え、サーバー側 refresh とクライアント側 refresh が同時に走る経路を作るなら、直前ローテーション分のグレース許容があるかを先に確認する。再利用検知が即ファミリー失効だと、競合が誤ログアウトに化ける。
検証方法
AT の有効期限を数十秒に縮め、(1) 公開ページを開いたまま期限切れ後にリロード・遷移してもログイン表示が維持されること、(2) 複数タブで同時に期限切れを起こしても強制ログアウトしないこと、を確認する。