Skip to content

Web: migrate auth store to shared /store API (RemoteOAuthStorage parity with TUI/CLI) #1548

Description

@cliffhall

Follow-up split out of #1514 (Auth cleanup), completed by #1531.

#1531 removed guided auth and added connect-time OAuth, install-level CIMD, per-server OAuth clear, and keychain rehydration for TUI/CLI. The remaining piece of #1514's "migrate web client auth store to /store API" scope is still open:

  • Migrate the web client's OAuth storage to the shared /store API (RemoteOAuthStorage) so it reads/writes the same oauth.json as the TUI/CLI file-based store, giving web ⇄ TUI ⇄ CLI parity.
  • Listed explicitly as a follow-up in Guided-auth removal, OAuth smoke testing, and TUI/CLI support #1531 ("Web shared OAuth store (RemoteOAuthStorage / oauth.json parity with TUI/CLI)").

Target branch: v2/main.


Scope & context (added post-hoc — this issue is the Wave-1 home for PR #1510's web-OAuth-storage migration)

This pre-existing issue was terse and cited no files, but it stands in as the Wave-1 owner of the RemoteOAuthStorage + async-hydration work from the #1510 decomposition (see tracking #1579). Delivered by PR #1592 onto the Wave-1 rollup branch 1579-wave-1 (reference implementation: #1510 head 33fac3f). The concrete scope:

Behavior

  • Web OAuth store migrates from BrowserOAuthStorage (sessionStorage) to backend-backed RemoteOAuthStorage (~/.mcp-inspector/storage/oauth.json), shared with TUI/CLI on the same host.
  • Introduces a single async hydration gate (ready() / getHydrationError()); all post-redirect reads and all saves await it. Clears run hydration-safe (defer until hydrated, never clobber the on-disk blob).
  • getCodeVerifier / getServerMetadata become async across the interface, propagated through the provider and consumers.

Files changed (delivered on 1579-wave-1)

  • core/auth/storage.tsready() + async hydration gate; async getCodeVerifier/getServerMetadata signatures
  • core/auth/oauth-storage.tsOAuthStorageBase hydration + hydration-safe clear*
  • core/auth/providers.ts — async codeVerifier/getServerMetadata
  • core/auth/store.tsskipHydration + normalizeServerUrl keying + raw-key migration
  • core/auth/connection-state.ts — awaits getServerMetadata (this is feat(web/apps): spec-conformant Apps host + CLI/deep-link path for programmatic review #1510's core/auth/state-machine.ts, renamed on current v2/main)
  • core/auth/node/storage-node.ts — honors MCP_INSPECTOR_OAUTH_STATE_PATH
  • core/storage/adapters/remote-storage.tskeepalive POSTs + surfaces persist failures
  • clients/web/src/lib/environmentFactory.tsthe load-bearing swap: wires web to RemoteOAuthStorage via the memoized getRemoteOAuthStorage(...) accessor
  • clients/web/src/lib/remoteOAuthStorage.ts — new memoized RemoteOAuthStorage accessor
  • clients/web/src/App.tsx — async hydration in the OAuth-callback flow
  • Tests: oauth-storage / storage-browser / storage-remote / oauthManager (async mocks) + integration auth/node/storage and storage/adapters

Verification: exhaustive @claude review to clean, coverage gate ≥90 on all four dims for the gated files, and an independent smoke/audit (backend round-trip through /api/storage/oauth, oauth.json shape matches TUI/CLI, clear-before-hydration preserves sibling tokens) — see the audit on this issue and the rollup verification in #1600.

Metadata

Metadata

Labels

v2Issues and PRs for v2

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions