feat: surface and decode the OAuth id_token in Connection Info (#2019)

When an authorization server returns an `id_token` alongside the access
token, the Inspector already persisted it and never showed it. Wire it
through to Connection Info as a viewer.

- Generalize `OAuthAccessTokenField` into `OAuthTokenField` (label + token),
  so the ID Token row reuses the existing copy control and "Decode JWT"
  toggle rather than duplicating them. Access-token behavior is unchanged.
- `oauthDetailsFromConnectionState` now surfaces `tokens.id_token` as
  `idToken`, omitted entirely when absent so no empty row renders.
- Docs: update the two `specification/` references to the renamed field.

This is deliberately a viewer, not a flow: no OIDC login mode, no signature
verification, and the `id_token` is never treated as a credential. The EMA
path is untouched. `id_token` is already in `maskSecrets`'
`JSON_SENSITIVE_KEYS`, so it stays masked in the Network tab — no gap.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-15 18:33:41 -04:00
commit 07cafeedbc
2 changed files with 211 additions and 36 deletions

View file

@ -334,7 +334,7 @@ When the user connects to a server with `oauth.enterpriseManaged: true` but inst
- **IdP session** (EMA only) — `none` / `logged_in` / `expired` from `idpSessions[issuer]`
- **Auth URL** — cached from an in-flight or completed OAuth flow (`OAuthFlowState`), when present
- **Scopes** — configured vs granted
- **Access token** — `OAuthAccessTokenField`: copy (raw), decode JWT in place (`core/auth/ema/jwt.ts` helpers); multi-line wrap with segment-aware breaking for JWTs
- **Access token** (and **ID token**, when the authorization server returned an `id_token`) — `OAuthTokenField`: copy (raw), decode JWT in place (`core/auth/ema/jwt.ts` helpers); multi-line wrap with segment-aware breaking for JWTs. Display only — the `id_token` is never treated as a credential (#2019)
In-flight OAuth flow state uses `OAuthFlowState` / `getOAuthFlowState()` / `getOAuthFlowStep()`. `getOAuthState()` is the persisted connection snapshot; flow state is separate and ephemeral.

View file

@ -294,7 +294,7 @@ Shown as a modal or dedicated screen after successful connection.
- Server capabilities: Tools, Resources, Prompts, Logging, Completions, Tasks, Experimental
- Client capabilities: Sampling, Elicitation, Roots, Tasks, Experimental
- Display server instructions if provided
- Show OAuth connection snapshot when applicable (`InspectorClient.getOAuthState()` → `OAuthConnectionState`): protocol, authorization status, client id, EMA IdP session, cached auth URL, scopes, access token with copy and in-place JWT decode (`OAuthAccessTokenField`)
- Show OAuth connection snapshot when applicable (`InspectorClient.getOAuthState()` → `OAuthConnectionState`): protocol, authorization status, client id, EMA IdP session, cached auth URL, scopes, and the stored tokens — access token, plus the `id_token` when the authorization server returned one — each with copy and in-place JWT decode (`OAuthTokenField`)
### Feature Screens