From c20fce9ba28e6b25a2bf5dd2243153244f2e69c4 Mon Sep 17 00:00:00 2001 From: cliffhall Date: Mon, 24 Aug 2026 07:35:40 -0400 Subject: [PATCH] docs(spec): align mid-session auth spec with the token_expired predicate Copilot review on #2105: specification/v2_auth_mid_session.md still said checkAuthChallengeSatisfied is satisfied for token_expired / unauthorized by any valid non-expired token. Only token_expired can short-circuit, and only for a provably unexpired JWT; invalid_token and unauthorized are always false (which the code already did before this branch). Signed-off-by: cliffhall --- specification/v2_auth_mid_session.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specification/v2_auth_mid_session.md b/specification/v2_auth_mid_session.md index 8c39883e..cf714040 100644 --- a/specification/v2_auth_mid_session.md +++ b/specification/v2_auth_mid_session.md @@ -206,7 +206,8 @@ export type AuthChallengeOutcome = Read-only check against **current storage** (and token expiry helpers). Used before starting visible OAuth — especially when a background browser tab regains focus and another tab may have already re-authenticated. Does **not** call the authorization server. -- **`token_expired` / `unauthorized`:** valid non-expired access token in storage. +- **`token_expired`:** a **provably** unexpired access token in storage — a JWT whose `exp` is still in the future (60s skew). Storage records no absolute expiry for an opaque token (`expires_in` is relative to an issuance instant that is never persisted), so "expiry unknown" returns **false**: the resource server has said the credential is dead, and no local evidence contradicts it. Otherwise an opaque token would be replayed forever ([#2051](https://github.com/modelcontextprotocol/inspector/issues/2051)). +- **`invalid_token` / `unauthorized`:** always **false** — the resource server explicitly rejected the credential. - **`insufficient_scope`:** stored/token scope is a superset of required / union scopes. Empty scope on an `insufficient_scope` challenge returns **false** (do not short-circuit). ### Strategy by protocol