fix(oauth): stop claiming the opt-out removes every offline_access

Copilot review round 2 on #2114. The setting was described as
guaranteeing "no offline_access, no forced prompt", which is not what
the SDK does.

`startAuthorization` appends `prompt=consent` for any `offline_access`
in the effective scope and never consults `grant_types`, and
`determineScope` skips its augmentation when the scope already carries
it. So the prompt still goes out when the user configured
`offline_access` in Scopes, or left Scopes blank and the resource
advertises it in `scopes_supported`. The flag removes the SDK's
*automatic* augmentation and nothing more; the docs, the help text and
the type say that now.

The form also flags the case a user can act on: opted out while
`offline_access` is still listed in Scopes. Whole-token match, so
`offline_access_extra` does not trip it.

Corrects the Clear stored OAuth state claim too. It clears the local
tokens and client information — it is not a revocation and cannot
reach the AS. A dynamically registered client re-registers on the next
connect (the new registration declaring only `authorization_code`); a
preconfigured `oauth.clientId` is reused unchanged.

Adds the two missing seam tests, both confirmed to fail without the
code they cover: App's connect wiring (deleting the spread fails two of
the three) and an /api/servers POST followed by a read-back, since a
200 alone never proved the opt-out persisted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hzwzS8UvBsr4yZm7o7sev
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-24 20:35:14 -04:00
commit fca3f1ce67

View file

@ -791,9 +791,14 @@ export interface InspectorServerSettings {
* Whether the Inspector declares the `refresh_token` grant in its OAuth
* client metadata for this server. `undefined` (the default) means on;
* persisted as `oauth.requestRefreshToken` only when explicitly off. Turning
* it off also drops the SDK's automatic `offline_access` scope and the
* it off drops the SDK's *automatic* `offline_access` scope and so the
* `prompt=consent` it forces — the Entra admin-consent failure in #2068.
*
* Only the automatic one: `startAuthorization` adds `prompt=consent` for any
* `offline_access` in the effective scope without consulting `grant_types`,
* so a scope the user configured (or one the resource advertises when the
* scope field is blank) still forces the prompt.
*
* Read at connect time like the rest of the OAuth block, so a live client
* keeps the metadata it was built with. It changes what the Inspector
* declares, not state the authorization server already holds: an existing