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>
128 lines
3 KiB
TypeScript
128 lines
3 KiB
TypeScript
// Types
|
|
export type {
|
|
OAuthStep,
|
|
AuthProtocol,
|
|
OAuthClientRegistrationKind,
|
|
MessageType,
|
|
StatusMessage,
|
|
OAuthFlowState,
|
|
OAuthConnectionState,
|
|
CallbackParams,
|
|
} from "./types.js";
|
|
export {
|
|
EMPTY_OAUTH_FLOW_STATE,
|
|
authProtocolFromEnterpriseManaged,
|
|
} from "./types.js";
|
|
|
|
export {
|
|
buildOAuthConnectionState,
|
|
hasPersistedOAuthServerState,
|
|
isServerOAuthConfigured,
|
|
protocolFromOAuthConfig,
|
|
} from "./connection-state.js";
|
|
export type { BuildOAuthConnectionStateParams } from "./connection-state.js";
|
|
|
|
export { ensureCimdClientRegistration } from "./cimd.js";
|
|
|
|
export { mcpAuth, type McpAuthOptions, type McpAuthResult } from "./mcpAuth.js";
|
|
export { computeScopeUnion, isStrictScopeSuperset } from "./scopes.js";
|
|
|
|
// Custom authorization-request parameters (#2018)
|
|
export {
|
|
RESERVED_AUTHORIZATION_PARAMS,
|
|
isReservedAuthorizationParam,
|
|
authorizationParamKeyError,
|
|
applyAuthorizationParams,
|
|
} from "./authorizationParams.js";
|
|
export type { ReservedAuthorizationParam } from "./authorizationParams.js";
|
|
|
|
// Storage
|
|
export type {
|
|
OAuthStorage,
|
|
IdpSessionState,
|
|
SaveClientInformationOptions,
|
|
} from "./storage.js";
|
|
export { getServerSpecificKey, OAUTH_STORAGE_KEYS } from "./storage.js";
|
|
|
|
// Providers
|
|
export type {
|
|
OAuthProviderConfig,
|
|
RedirectUrlProvider,
|
|
OAuthNavigation,
|
|
OAuthNavigationCallback,
|
|
} from "./providers.js";
|
|
export {
|
|
MutableRedirectUrlProvider,
|
|
ConsoleNavigation,
|
|
CallbackNavigation,
|
|
BaseOAuthClientProvider,
|
|
} from "./providers.js";
|
|
|
|
// Utilities
|
|
export {
|
|
parseHttpUrl,
|
|
parseOAuthCallbackParams,
|
|
generateOAuthState,
|
|
parseOAuthState,
|
|
generateOAuthErrorDescription,
|
|
formatOAuthFailureDetail,
|
|
isUnauthorizedError,
|
|
} from "./utils.js";
|
|
|
|
export type {
|
|
AuthChallenge,
|
|
AuthChallengeReason,
|
|
AuthChallengeOutcome,
|
|
HandleAuthChallengeOptions,
|
|
ParseAuthChallengeContext,
|
|
WwwAuthenticateBearerParams,
|
|
} from "./challenge.js";
|
|
export {
|
|
AuthChallengeError,
|
|
AuthRecoveryRequiredError,
|
|
parseAuthChallengeFromError,
|
|
parseAuthChallengeFromResponse,
|
|
parseScopeString,
|
|
parseWwwAuthenticateBearer,
|
|
unionAuthorizationScopes,
|
|
isAuthChallengeError,
|
|
isConnectAuthRecoveryError,
|
|
findNestedAuthError,
|
|
EMA_STEP_UP_PENDING_URL,
|
|
} from "./challenge.js";
|
|
|
|
export {
|
|
isStandardOAuthStepUp,
|
|
isEmaStepUp,
|
|
isStepUpConfirmation,
|
|
stepUpConfirmMessage,
|
|
stepUpFollowUpMessage,
|
|
stepUpModalTitle,
|
|
stepUpAuthorizeActionLabel,
|
|
emaStepUpInProgressMessage,
|
|
emaStepUpSuccessMessage,
|
|
emaStepUpFailureMessage,
|
|
stepUpAdditionalScopes,
|
|
stepUpInsufficientScopeMessage,
|
|
oauthPreRedirectToastCopy,
|
|
isReAuthBannerReason,
|
|
reAuthBannerMessage,
|
|
lostAuthorizationStateTitle,
|
|
lostAuthorizationStateMessage,
|
|
lostAuthorizationStateActionLabel,
|
|
issuerMismatchTitle,
|
|
issuerMismatchMessage,
|
|
issuerBindingFailureCopy,
|
|
type OAuthInteractiveAuthKind,
|
|
} from "./oauthUx.js";
|
|
|
|
export {
|
|
findIssuerBindingFailure,
|
|
type IssuerBindingFailure,
|
|
} from "./issuerBinding.js";
|
|
|
|
// Discovery
|
|
export { discoverScopes } from "./discovery.js";
|
|
|
|
// Logging (re-exported from core/logging)
|
|
export { silentLogger } from "../logging/index.js";
|