diff --git a/client/src/components/AuthDebugger.tsx b/client/src/components/AuthDebugger.tsx index ec09963ec..3b89de299 100644 --- a/client/src/components/AuthDebugger.tsx +++ b/client/src/components/AuthDebugger.tsx @@ -1,6 +1,6 @@ import { useCallback, useMemo, useEffect } from "react"; import { Button } from "@/components/ui/button"; -import { DebugInspectorOAuthClientProvider } from "../lib/auth"; +import { DebugInspectorOAuthClientProvider, InspectorOAuthClientProvider } from "../lib/auth"; import { AlertCircle } from "lucide-react"; import { AuthDebuggerState, EMPTY_DEBUGGER_STATE } from "../lib/auth-types"; import { OAuthFlowProgress } from "./OAuthFlowProgress"; @@ -149,11 +149,13 @@ const AuthDebugger = ({ latestError: null, }; + // Use regular provider for quick flow (automatic callback) + const provider = new InspectorOAuthClientProvider(serverUrl); const oauthMachine = new OAuthStateMachine(serverUrl, (updates) => { // Update our temporary state during the process currentState = { ...currentState, ...updates }; // But don't call updateAuthState yet - }); + }, provider); // Manually step through each stage of the OAuth flow while (currentState.oauthStep !== "complete") { diff --git a/client/src/lib/oauth-state-machine.ts b/client/src/lib/oauth-state-machine.ts index 24b62084c..cbefd91e7 100644 --- a/client/src/lib/oauth-state-machine.ts +++ b/client/src/lib/oauth-state-machine.ts @@ -1,5 +1,5 @@ import { OAuthStep, AuthDebuggerState } from "./auth-types"; -import { DebugInspectorOAuthClientProvider } from "./auth"; +import { DebugInspectorOAuthClientProvider, InspectorOAuthClientProvider } from "./auth"; import { discoverAuthorizationServerMetadata, registerClient, @@ -17,7 +17,7 @@ import { generateOAuthState } from "@/utils/oauthUtils"; export interface StateMachineContext { state: AuthDebuggerState; serverUrl: string; - provider: DebugInspectorOAuthClientProvider; + provider: DebugInspectorOAuthClientProvider | InspectorOAuthClientProvider; updateState: (updates: Partial) => void; } @@ -62,7 +62,10 @@ export const oauthTransitions: Record = { throw new Error("Failed to discover OAuth metadata"); } const parsedMetadata = await OAuthMetadataSchema.parseAsync(metadata); - context.provider.saveServerMetadata(parsedMetadata); + // Only save server metadata if provider supports it (debug provider) + if ('saveServerMetadata' in context.provider) { + context.provider.saveServerMetadata(parsedMetadata); + } context.updateState({ resourceMetadata, resource, @@ -160,15 +163,20 @@ export const oauthTransitions: Record = { token_request: { canTransition: async (context) => { + const hasServerMetadata = 'getServerMetadata' in context.provider + ? !!context.provider.getServerMetadata() + : !!context.state.oauthMetadata; return ( !!context.state.authorizationCode && - !!context.provider.getServerMetadata() && + hasServerMetadata && !!(await context.provider.clientInformation()) ); }, execute: async (context) => { const codeVerifier = context.provider.codeVerifier(); - const metadata = context.provider.getServerMetadata()!; + const metadata = 'getServerMetadata' in context.provider + ? context.provider.getServerMetadata()! + : context.state.oauthMetadata!; const clientInformation = (await context.provider.clientInformation())!; const tokens = await exchangeAuthorization(context.serverUrl, { @@ -200,10 +208,12 @@ export class OAuthStateMachine { constructor( private serverUrl: string, private updateState: (updates: Partial) => void, + private provider?: DebugInspectorOAuthClientProvider | InspectorOAuthClientProvider, ) {} async executeStep(state: AuthDebuggerState): Promise { - const provider = new DebugInspectorOAuthClientProvider(this.serverUrl); + // Use provided provider or default to debug provider for backward compatibility + const provider = this.provider || new DebugInspectorOAuthClientProvider(this.serverUrl); const context: StateMachineContext = { state, serverUrl: this.serverUrl,