feat(oauth): make the refresh_token grant opt-out per server
The Inspector always declared `refresh_token` in its OAuth client metadata. The SDK's `determineScope()` then appends `offline_access` whenever the authorization server advertises it and the client declares that grant, and `startAuthorization()` appends `prompt=consent` whenever `offline_access` is in scope. Against Microsoft Entra ID that forced consent prompt routes a non-admin user into the admin-consent workflow and fails with AADSTS90094 — even after a tenant admin has consented. Adds a per-server "Request refresh token" setting (default on) that drops the grant from the client metadata, breaking that chain at its source. Persisted as `oauth.requestRefreshToken` and written only when off, so entries that never touch it keep a byte-stable round-trip. Web edits it in Server Settings → Authorization; the CLI and TUI pick it up from the same per-server settings via `buildRunnerClientAuthOptions`. 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:
parent
9d0448b644
commit
e2fb78d999
1 changed files with 405 additions and 5 deletions
|
|
@ -87,7 +87,8 @@ export function buildRunnerClientAuthOptions(
|
|||
savedSettings.oauthScopes ||
|
||||
serverAuthorizationParams ||
|
||||
serverEndpointOverrides ||
|
||||
savedSettings.enterpriseManaged)
|
||||
savedSettings.enterpriseManaged ||
|
||||
savedSettings.oauthRequestRefreshToken === false)
|
||||
? {
|
||||
...(savedSettings.oauthClientId && {
|
||||
clientId: savedSettings.oauthClientId,
|
||||
|
|
@ -105,6 +106,11 @@ export function buildRunnerClientAuthOptions(
|
|||
...(savedSettings.enterpriseManaged && {
|
||||
enterpriseManaged: true,
|
||||
}),
|
||||
// #2068: only the explicit opt-out is forwarded; omitting the key
|
||||
// leaves the provider's default (declare `refresh_token`) in place.
|
||||
...(savedSettings.oauthRequestRefreshToken === false && {
|
||||
requestRefreshToken: false,
|
||||
}),
|
||||
}
|
||||
: undefined;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue