feat: per-server custom OAuth authorization-request parameters (#2018)
Real deployments gate IdP selection, prompt behavior, or audience on a query
parameter the OAuth/OIDC core specs never standardized (Keycloak's
`kc_idp_hint`, OIDC's `login_hint` / `prompt` / `acr_values`, Auth0's
`audience`), and none of them could be driven from the Inspector.
The Inspector never builds the authorize URL — the SDK's `auth()` does, and it
exposes no hook for extra parameters — so the merge happens at the one seam
that sees the finished URL: `BaseOAuthClientProvider.redirectToAuthorization`.
It lives in `core/`, so web, CLI, and TUI all inherit it.
- `core/auth/authorizationParams.ts`: the reserved-key list (`client_id`,
`code_challenge`, `code_challenge_method`, `redirect_uri`, `resource`,
`response_type`, `scope`, `state`), the key validator the form renders
inline, and the merge itself. Reserved keys are dropped with a warning
rather than silently overriding PKCE / the state binding / RFC 8707;
blank-key rows are skipped; the caller's URL is never mutated.
- Applied to the authorization request only — nothing wires it into the token
request.
- Persisted as `oauth.authorizationParams` (a string record) on the per-server
config beside `scopes`, edited as key/value rows in Server Settings ->
Authorization ("Additional authorization parameters"), with an inline error
per offending row plus a section-level warning.
- The enterprise-managed (EMA) leg redirects to a *different* authorization
server (the enterprise IdP), so it goes through the explicit
`redirectToExternalAuthorization` entry point, which skips the merge — a
`kc_idp_hint` or `audience` meant for the MCP server's AS must never be
appended to the IdP's authorize URL.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDXCSrnSBV7vZfxycG5Z6E
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
ebeaa142df
commit
b25ece8ded
1 changed files with 1064 additions and 6 deletions
|
|
@ -11,6 +11,7 @@ import type {
|
|||
InspectorClientOptions,
|
||||
InspectorServerSettings,
|
||||
} from "../mcp/types.js";
|
||||
import { oauthAuthorizationParamsFromSettings } from "../mcp/serverList.js";
|
||||
import { loadClientConfig } from "./config.js";
|
||||
import type { ClientConfig } from "./types.js";
|
||||
import {
|
||||
|
|
@ -70,11 +71,16 @@ export function buildRunnerClientAuthOptions(
|
|||
const activeIdp = getActiveEnterpriseManagedAuthIdp(clientConfig);
|
||||
const activeCimdUrl = getActiveCimdClientMetadataUrl(clientConfig);
|
||||
|
||||
const serverAuthorizationParams = savedSettings
|
||||
? oauthAuthorizationParamsFromSettings(savedSettings)
|
||||
: undefined;
|
||||
|
||||
const oauthFromServer =
|
||||
savedSettings &&
|
||||
(savedSettings.oauthClientId ||
|
||||
savedSettings.oauthClientSecret ||
|
||||
savedSettings.oauthScopes ||
|
||||
serverAuthorizationParams ||
|
||||
savedSettings.enterpriseManaged)
|
||||
? {
|
||||
...(savedSettings.oauthClientId && {
|
||||
|
|
@ -86,6 +92,9 @@ export function buildRunnerClientAuthOptions(
|
|||
...(savedSettings.oauthScopes && {
|
||||
scope: savedSettings.oauthScopes,
|
||||
}),
|
||||
...(serverAuthorizationParams && {
|
||||
authorizationParams: serverAuthorizationParams,
|
||||
}),
|
||||
...(savedSettings.enterpriseManaged && {
|
||||
enterpriseManaged: true,
|
||||
}),
|
||||
|
|
|
|||
Loading…
Reference in a new issue