Feat/mid session auth#1607
Closed
BobDickinson wants to merge 4 commits into
Closed
Conversation
Contributor
Author
|
Superseded by same-repo PR #1608 (branch now on modelcontextprotocol/inspector for CI + checks). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Mid-session authorization (web, TUI, CLI)
Closes #1526
Summary
Implements mid-session authorization for Inspector v2 as specified in
specification/v2_auth_mid_session.md: detecting MCP 401/403 auth challenges after connect, normalizing them toAuthChallenge, running sharedOAuthManager.handleAuthChallenge()recovery, and restoring the session without forcing a full disconnect/reconnect cycle.Covers standard OAuth (token refresh, re-login, SEP-2350 step-up with scope union) and enterprise-managed auth (EMA) (silent legs 2–3 re-mint, IdP leg 1 when needed). All three surfaces share
core/auth/challenge.tsand core recovery logic; UX and wire delivery differ by client as the spec describes.Builds on connect-time OAuth/EMA already in v2 and aligns with
v2_auth_hardening.md(scope union, issuer handling hooks) without waiting on the v2 SDK transport retry PR.What this delivers
Shared core
AuthChallengeparsing fromWWW-Authenticate(401/403,insufficient_scope, etc.).handleAuthChallenge()outcomes:satisfied,step_up_confirm(EMA/web deferral),interactive,failed.checkAuthChallengeSatisfied()— storage-only short-circuit before starting visible OAuth.completeOAuthFlow().oauthUx.ts— shared copy for step-up modals, EMA vs standard OAuth, toasts, re-auth banner text.runRunnerInteractiveOAuth()— shared TUI/CLI loopback callback flow (127.0.0.1:6276).formatOAuthFailureDetail()— human-readable OAuth failure messages (no raw Zod JSON in UI).Web (remote transport)
Note: The main challenge with the web app is that re-auth is generally detected on the backend (the Node side of the API), but authentication often needs to happen on the web app side of the API. So we needed a mechanism to notify the web app to trigger a re-auth (with details) and a way for the web app to then communicate results and populate the remote tranport with the new authenication state (esp tokens). Also, because re-auth can navigate away from Inspector and redirect back to inspector when complete, we needed a mechanism to record and restore app state (similar to how we record HTTP messages across an auth gap), such that after auth we show the same server connected, are on the same table, and ideally with the same state (entered tool call params, for example).
POST /api/mcp/send(HTTP 200 + retry once after recovery) vs ambient challenges on SSE.POST /api/mcp/auth-state— hot-swap tokens on the node session without tearing down transport.auth()).StepUpAuthModal— user confirmation before standard-OAuth redirect or EMA re-mint/IdP (Inspector-as-testing-tool visibility).sessionStorage) — restore server, app tab, and panel UI after full-page redirect; explicit disconnect clears snapshot and resets to Servers.pendingReauth— defer interactive OAuth when browser tab is hidden; resume on visibility.ReAuthBanner— persistent re-auth when OAuth aborts or callback fails.TUI & CLI (direct transport)
InspectorClient.withDirectAuthRecovery()anddirectAuthRecoverytransport intercept until v2 SDK owns silent retry.handleAuthChallenge, loopback callback, clear OAuth (S).cliOAuth.ts— connect-time and mid-session interactive OAuth; y/N step-up prompt; one-shot RPC retry after recovery.Test infrastructure
test-servers/) with per-capabilityrequiredScopesand AS-levelscopesSupported(in support of step-up auth).oauth-step-up-demo.json(standard step-up),xaa-ema-http.json(EMA).v2_auth_smoke_testing.md§5+.Spec & docs
v2_auth_mid_session.md— design reference (architecture, client matrix, resume snapshot, UX tables).v2_auth_smoke_testing.md— hosted + local smoke scenarios.v2_auth_ema.md— EMA step-up web confirmation.v2_scope.md— OAuth handling scope entry updated.Testing
Automated (
npm run validate) — all passed:Includes unit tests for challenge parsing, scope union,
oauthUxcopy,OAuthManager.handleAuthChallenge, web App OAuth resume lifecycle, TUI EMA step-up and Auth-tab flows, CLI interactive step-up prompts, remote auth-state propagation, and composable test-server scope enforcement.Manual validation follows
v2_auth_smoke_testing.md: standard step-up onoauth-step-up-demo, EMA step-up ontest-server-ema, OAuth callback abort, and hosted servers (GitHub, Stytch, etc.).Reviewer notes