@@ -13,12 +13,21 @@ import {
1313 OAuthProtectedResourceMetadata ,
1414} from "@modelcontextprotocol/sdk/shared/auth.js" ;
1515import { generateOAuthState } from "@/utils/oauthUtils" ;
16+ import { InspectorConfig } from "./configurationTypes" ;
17+ import {
18+ discoverAuthorizationServerMetadataViaProxy ,
19+ discoverOAuthProtectedResourceMetadataViaProxy ,
20+ registerClientViaProxy ,
21+ exchangeAuthorizationViaProxy ,
22+ } from "./oauth-proxy" ;
1623
1724export interface StateMachineContext {
1825 state : AuthDebuggerState ;
1926 serverUrl : string ;
2027 provider : DebugInspectorOAuthClientProvider ;
2128 updateState : ( updates : Partial < AuthDebuggerState > ) => void ;
29+ connectionType : "direct" | "proxy" ;
30+ config : InspectorConfig ;
2231}
2332
2433export interface StateTransition {
@@ -36,9 +45,18 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
3645 let resourceMetadata : OAuthProtectedResourceMetadata | null = null ;
3746 let resourceMetadataError : Error | null = null ;
3847 try {
39- resourceMetadata = await discoverOAuthProtectedResourceMetadata (
40- context . serverUrl ,
41- ) ;
48+ // Use proxy if connectionType is "proxy"
49+ if ( context . connectionType === "proxy" ) {
50+ resourceMetadata =
51+ await discoverOAuthProtectedResourceMetadataViaProxy (
52+ context . serverUrl ,
53+ context . config ,
54+ ) ;
55+ } else {
56+ resourceMetadata = await discoverOAuthProtectedResourceMetadata (
57+ context . serverUrl ,
58+ ) ;
59+ }
4260 if ( resourceMetadata ?. authorization_servers ?. length ) {
4361 authServerUrl = new URL ( resourceMetadata . authorization_servers [ 0 ] ) ;
4462 }
@@ -57,7 +75,15 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
5775 resourceMetadata ?? undefined ,
5876 ) ;
5977
60- const metadata = await discoverAuthorizationServerMetadata ( authServerUrl ) ;
78+ // Use proxy if connectionType is "proxy"
79+ const metadata =
80+ context . connectionType === "proxy"
81+ ? await discoverAuthorizationServerMetadataViaProxy (
82+ authServerUrl ,
83+ context . config ,
84+ )
85+ : await discoverAuthorizationServerMetadata ( authServerUrl ) ;
86+
6187 if ( ! metadata ) {
6288 throw new Error ( "Failed to discover OAuth metadata" ) ;
6389 }
@@ -86,19 +112,33 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
86112 const scopesSupported =
87113 context . state . resourceMetadata ?. scopes_supported ||
88114 metadata . scopes_supported ;
89- // Add all supported scopes to client registration
90- if ( scopesSupported ) {
115+ // Add all supported scopes to client registration (only if non-empty)
116+ if ( scopesSupported && scopesSupported . length > 0 ) {
91117 clientMetadata . scope = scopesSupported . join ( " " ) ;
92118 }
93119 }
94120
95121 // Try Static client first, with DCR as fallback
96122 let fullInformation = await context . provider . clientInformation ( ) ;
97123 if ( ! fullInformation ) {
98- fullInformation = await registerClient ( context . serverUrl , {
99- metadata,
100- clientMetadata,
101- } ) ;
124+ // Use proxy if connectionType is "proxy"
125+ if ( context . connectionType === "proxy" ) {
126+ if ( ! metadata . registration_endpoint ) {
127+ throw new Error (
128+ "No registration endpoint available for dynamic client registration" ,
129+ ) ;
130+ }
131+ fullInformation = await registerClientViaProxy (
132+ metadata . registration_endpoint ,
133+ clientMetadata ,
134+ context . config ,
135+ ) ;
136+ } else {
137+ fullInformation = await registerClient ( context . serverUrl , {
138+ metadata,
139+ clientMetadata,
140+ } ) ;
141+ }
102142 context . provider . saveClientInformation ( fullInformation ) ;
103143 }
104144
@@ -178,18 +218,50 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
178218 const metadata = context . provider . getServerMetadata ( ) ! ;
179219 const clientInformation = ( await context . provider . clientInformation ( ) ) ! ;
180220
181- const tokens = await exchangeAuthorization ( context . serverUrl , {
182- metadata,
183- clientInformation,
184- authorizationCode : context . state . authorizationCode ,
185- codeVerifier,
186- redirectUri : context . provider . redirectUrl ,
187- resource : context . state . resource
188- ? context . state . resource instanceof URL
189- ? context . state . resource
190- : new URL ( context . state . resource )
191- : undefined ,
192- } ) ;
221+ let tokens ;
222+
223+ // Use proxy if connectionType is "proxy"
224+ if ( context . connectionType === "proxy" ) {
225+ // Build the token request parameters
226+ const params : Record < string , string > = {
227+ grant_type : "authorization_code" ,
228+ code : context . state . authorizationCode ,
229+ redirect_uri : context . provider . redirectUrl ,
230+ code_verifier : codeVerifier ,
231+ client_id : clientInformation . client_id ,
232+ } ;
233+
234+ if ( clientInformation . client_secret ) {
235+ params . client_secret = clientInformation . client_secret ;
236+ }
237+
238+ if ( context . state . resource ) {
239+ const resourceUrl =
240+ context . state . resource instanceof URL
241+ ? context . state . resource . toString ( )
242+ : context . state . resource ;
243+ params . resource = resourceUrl ;
244+ }
245+
246+ tokens = await exchangeAuthorizationViaProxy (
247+ metadata . token_endpoint ,
248+ params ,
249+ context . config ,
250+ ) ;
251+ } else {
252+ tokens = await exchangeAuthorization ( context . serverUrl , {
253+ metadata,
254+ clientInformation,
255+ authorizationCode : context . state . authorizationCode ,
256+ codeVerifier,
257+ redirectUri : context . provider . redirectUrl ,
258+ resource : context . state . resource
259+ ? context . state . resource instanceof URL
260+ ? context . state . resource
261+ : new URL ( context . state . resource )
262+ : undefined ,
263+ } ) ;
264+ }
193265
194266 context . provider . saveTokens ( tokens ) ;
195267 context . updateState ( {
@@ -211,6 +283,8 @@ export class OAuthStateMachine {
211283 constructor (
212284 private serverUrl : string ,
213285 private updateState : ( updates : Partial < AuthDebuggerState > ) => void ,
286+ private connectionType : "direct" | "proxy" ,
287+ private config : InspectorConfig ,
214288 ) { }
215289
216290 async executeStep ( state : AuthDebuggerState ) : Promise < void > {
@@ -220,6 +294,8 @@ export class OAuthStateMachine {
220294 serverUrl : this . serverUrl ,
221295 provider,
222296 updateState : this . updateState ,
297+ connectionType : this . connectionType ,
298+ config : this . config ,
223299 } ;
224300
225301 const transition = oauthTransitions [ state . oauthStep ] ;
0 commit comments