@@ -420,7 +420,7 @@ export async function connectToRemoteServer(
420
420
421
421
// Handle invalid_client errors by clearing all auth data
422
422
if ( errorType === 'invalid_client' ) {
423
- log ( 'Client registration is invalid. Clearing all stored auth data and restarting registration ...' )
423
+ log ( 'Client registration is invalid. Clearing all stored auth data and starting fresh auth flow ...' )
424
424
if ( DEBUG ) debugLog ( 'Invalid client registration detected, clearing all auth data' )
425
425
426
426
// Clear all auth data to force complete re-registration
@@ -500,8 +500,8 @@ export async function connectToRemoteServer(
500
500
const authErrorType = classifyAuthError ( authError )
501
501
if ( authErrorType === 'invalid_client' ) {
502
502
log ( 'Token exchange failed due to invalid client. This suggests the client registration was deleted on the server.' )
503
- log ( 'Clearing all stored auth data to force complete re-registration on next attempt ...' )
504
- if ( DEBUG ) debugLog ( 'Token exchange failed with invalid_client, clearing all auth data' )
503
+ log ( 'Clearing all stored auth data and immediately starting fresh auth flow ...' )
504
+ if ( DEBUG ) debugLog ( 'Token exchange failed with invalid_client, clearing all auth data and restarting auth ' )
505
505
506
506
// Clear all auth data to force complete re-registration
507
507
const extendedProvider = authProvider as ExtendedOAuthClientProvider
@@ -512,13 +512,67 @@ export async function connectToRemoteServer(
512
512
// Reset retry state since we're starting fresh
513
513
resetAuthRetryState ( serverUrlHash )
514
514
515
- // Create a more descriptive error message
516
- const descriptiveError = new Error (
517
- 'Client registration appears to be invalid or deleted on the server. ' +
518
- 'Cleared all local auth data. Please try connecting again to re-register.' ,
519
- )
520
- descriptiveError . stack = authError . stack
521
- throw descriptiveError
515
+ // Immediately restart the auth flow with fresh registration
516
+ log ( 'Starting fresh authentication flow...' )
517
+ if ( DEBUG ) debugLog ( 'Restarting auth flow after clearing invalid client data' )
518
+
519
+ const { waitForAuthCode, skipBrowserAuth } = await authInitializer ( )
520
+
521
+ if ( skipBrowserAuth ) {
522
+ log ( 'Authentication required but skipping browser auth - using shared auth' )
523
+ if ( DEBUG ) debugLog ( 'Authentication required but skipping browser auth - using shared auth' )
524
+ } else {
525
+ log ( 'Authentication required. Waiting for authorization...' )
526
+ if ( DEBUG ) debugLog ( 'Authentication required. Waiting for authorization...' )
527
+ }
528
+
529
+ // Wait for the authorization code from the callback
530
+ if ( DEBUG ) debugLog ( 'Waiting for auth code from callback server' )
531
+ const newCode = await waitForAuthCode ( )
532
+ if ( DEBUG ) debugLog ( 'Received new auth code from callback server' )
533
+
534
+ // Try token exchange again with the new code
535
+ log ( 'Completing fresh authorization...' )
536
+ if ( DEBUG ) debugLog ( 'Completing fresh authorization with new code' )
537
+ try {
538
+ await transport . finishAuth ( newCode )
539
+ if ( DEBUG ) debugLog ( 'Fresh authorization completed successfully' )
540
+ } catch ( freshAuthError : any ) {
541
+ // If the fresh auth also fails with invalid_client, we have a deeper problem
542
+ const freshErrorType = classifyAuthError ( freshAuthError )
543
+ if ( freshErrorType === 'invalid_client' ) {
544
+ log ( 'Fresh authentication also failed with invalid client. This suggests a persistent server-side issue.' )
545
+ if ( DEBUG ) debugLog ( 'Fresh auth also failed with invalid_client, giving up' )
546
+ throw new Error (
547
+ 'Fresh client registration also failed with invalid_client error. ' +
548
+ 'This suggests a persistent server-side issue. Please check server configuration.' ,
549
+ )
550
+ }
551
+ // For other errors, just re-throw
552
+ throw freshAuthError
553
+ }
554
+
555
+ // Reset retry state on successful auth
556
+ resetAuthRetryState ( serverUrlHash )
557
+
558
+ // Continue with recursive reconnection
559
+ if ( recursionReasons . has ( REASON_AUTH_NEEDED ) ) {
560
+ const errorMessage = `Already attempted reconnection for reason: ${ REASON_AUTH_NEEDED } . Giving up.`
561
+ log ( errorMessage )
562
+ if ( DEBUG )
563
+ debugLog ( 'Already attempted auth reconnection, giving up' , {
564
+ recursionReasons : Array . from ( recursionReasons ) ,
565
+ } )
566
+ throw new Error ( errorMessage )
567
+ }
568
+
569
+ // Track this reason for recursion
570
+ recursionReasons . add ( REASON_AUTH_NEEDED )
571
+ log ( `Recursively reconnecting for reason: ${ REASON_AUTH_NEEDED } ` )
572
+ if ( DEBUG ) debugLog ( 'Recursively reconnecting after fresh auth' , { recursionReasons : Array . from ( recursionReasons ) } )
573
+
574
+ // Recursively call connectToRemoteServer with the updated recursion tracking
575
+ return connectToRemoteServer ( client , serverUrl , authProvider , headers , authInitializer , transportStrategy , recursionReasons )
522
576
}
523
577
524
578
throw authError
0 commit comments