Skip to content

fix(oauth): stale in-memory token blocks re-auth for the life of the proxy process #250

Description

@smileygames

目的

ブラウザで認可を完了して ~/.github-rag-mcp/oauth-tokens.json が更新されているのに、MCP 呼び出しが Authentication required を返し続ける状態を解消する。プロキシプロセスを再起動するまで復旧しない。

観測(2026-08-21)

  • Master 報告: GitHub の認可ページは「認可済み」の表示が出る。それでも mcp__github-rag-mcp__search は毎回 Authentication required を返す。「また認証バグってる」= 再発。
  • 実測: ~/.github-rag-mcp/oauth-tokens.jsonoauth-client.json はどちらも当日 07:45 に更新されていた。認可フロー自体は完走してトークンが書かれている。それでも直後の呼び出しが同じエラーを返す。
  • 直前の文脈として、GitHub App を org 所有の liplus-rag-mcp-org へ差し替えている。旧 App 下で発行された refresh token は新 App の grant に解決しないため、refresh は失敗する側に倒れる。

前提(mcp-server/server/index.js の literal)

getAccessToken() (:321-343):

  • _cachedTokens が falsy のときだけ loadTokens() でディスクから読む (:322-324)。
  • _cachedTokens が truthy で expires_at 超過、かつ refresh に失敗すると catch で握りつぶして下へ抜ける (:331-339)。
  • 最後に _cachedTokens = await performOAuthFlow() (:341)。

performOAuthFlow() (:269-288) はブラウザ認可の完了を 2〜3 秒しか待たず、間に合わなければ OAuthPendingError を投げる。人間の認可操作がこの秒数に収まることはないので、初回が Authentication required を返すのは設計どおり。

欠陥

performOAuthFlow() が throw した場合、_cachedTokens への代入 (:341) は起きない。古いトークンが _cachedTokens に載ったまま残る

結果、次の呼び出しでも:

  1. _cachedTokens は truthy なので loadTokens() を通らない —— 認可フローが書き終えた新しいトークンをディスクから読み直す経路が無い
  2. 期限切れなので refresh を試み、旧 App 由来で失敗する。
  3. また performOAuthFlow() に落ちて throw。

これがプロセスの寿命のあいだ繰り返される。ディスク上には有効なトークンがあるのに、メモリ上の古い値が読み直しを永久に塞ぐ。再起動でしか抜けられないのは、_cachedTokens がプロセスと同じ寿命のモジュール変数だからである。

onUnauthorized (:357-360) は _cachedTokens = null を行うが、これは Worker が 401 を返した経路専用であり、本件の refresh 失敗経路には掛からない。

修理の方向(未確定)

  • refresh 失敗の catch で _cachedTokens = null に落とし、次回にディスク読み直しを起こす。
  • あるいは performOAuthFlow() が throw する直前に _cachedTokens を明示的に無効化する。

どちらも「メモリ上の値がディスクの新しい値を覆い隠さない」という一点を満たす。実装時にどちらが load-bearing か判定する。

関連

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug動いていない、壊れているforming本文を再構築しながら要求を整えている状態

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions