@@ -92,8 +92,6 @@ interface AuthService {
92
92
/**
93
93
* Replaces the profile for a connection with a new one.
94
94
*
95
- * This will invalidate the connection, potentially requiring a re-authentication.
96
- *
97
95
* **IAM connections are not implemented**
98
96
*/
99
97
updateConnection ( connection : Pick < Connection , 'id' > , profile : Profile ) : Promise < Connection >
@@ -166,9 +164,10 @@ export class Auth implements AuthService, ConnectionManager {
166
164
}
167
165
}
168
166
169
- public async reauthenticate ( { id } : Pick < SsoConnection , 'id' > ) : Promise < SsoConnection >
170
- public async reauthenticate ( { id } : Pick < IamConnection , 'id' > ) : Promise < IamConnection >
171
- public async reauthenticate ( { id } : Pick < Connection , 'id' > ) : Promise < Connection > {
167
+ public async reauthenticate ( { id } : Pick < SsoConnection , 'id' > , invalidate ?: boolean ) : Promise < SsoConnection >
168
+ public async reauthenticate ( { id } : Pick < IamConnection , 'id' > , invalidate ?: boolean ) : Promise < IamConnection >
169
+ public async reauthenticate ( { id } : Pick < Connection , 'id' > , invalidate ?: boolean ) : Promise < Connection > {
170
+ const shouldInvalidate = invalidate ?? true
172
171
const profile = this . store . getProfileOrThrow ( id )
173
172
if ( profile . type === 'sso' ) {
174
173
const provider = this . getSsoTokenProvider ( id , profile )
@@ -177,13 +176,13 @@ export class Auth implements AuthService, ConnectionManager {
177
176
// so we need to set it here.
178
177
await telemetry . aws_loginWithBrowser . run ( async span => {
179
178
span . record ( { isReAuth : true , credentialStartUrl : profile . startUrl } )
180
- await this . authenticate ( id , ( ) => provider . createToken ( ) )
179
+ await this . authenticate ( id , ( ) => provider . createToken ( ) , shouldInvalidate )
181
180
} )
182
181
183
182
return this . getSsoConnection ( id , profile )
184
183
} else {
185
184
const provider = await this . getCredentialsProvider ( id , profile )
186
- await this . authenticate ( id , ( ) => this . createCachedCredentials ( provider ) )
185
+ await this . authenticate ( id , ( ) => this . createCachedCredentials ( provider ) , shouldInvalidate )
187
186
188
187
return this . getIamConnection ( id , profile )
189
188
}
@@ -383,14 +382,24 @@ export class Auth implements AuthService, ConnectionManager {
383
382
await this . validateConnection ( connection . id , profile )
384
383
}
385
384
386
- public async updateConnection ( connection : Pick < SsoConnection , 'id' > , profile : SsoProfile ) : Promise < SsoConnection >
387
- public async updateConnection ( connection : Pick < Connection , 'id' > , profile : Profile ) : Promise < Connection > {
385
+ public async updateConnection (
386
+ connection : Pick < SsoConnection , 'id' > ,
387
+ profile : SsoProfile ,
388
+ invalidate ?: boolean
389
+ ) : Promise < SsoConnection >
390
+ public async updateConnection (
391
+ connection : Pick < Connection , 'id' > ,
392
+ profile : Profile ,
393
+ invalidate ?: boolean
394
+ ) : Promise < Connection > {
388
395
getLogger ( ) . info ( `auth: Updating connection ${ connection . id } ` )
389
396
if ( profile . type === 'iam' ) {
390
397
throw new Error ( 'Updating IAM connections is not supported' )
391
398
}
392
399
393
- await this . invalidateConnection ( connection . id , { skipGlobalLogout : true } )
400
+ if ( invalidate ?? false ) {
401
+ await this . invalidateConnection ( connection . id , { skipGlobalLogout : true } )
402
+ }
394
403
395
404
const newProfile = await this . store . updateProfile ( connection . id , profile )
396
405
const updatedConn = this . getSsoConnection ( connection . id , newProfile as StoredProfile < SsoProfile > )
@@ -554,15 +563,17 @@ export class Auth implements AuthService, ConnectionManager {
554
563
}
555
564
}
556
565
557
- return runCheck ( ) . catch ( err => this . handleSsoTokenError ( id , err ) )
566
+ return runCheck ( ) . catch ( async err => {
567
+ await this . handleSsoTokenError ( id , err ) // may throw without setting state to invalid - this is intended.
568
+ await this . updateConnectionState ( id , 'invalid' )
569
+ } )
558
570
}
559
571
560
572
private async handleSsoTokenError ( id : Connection [ 'id' ] , err : unknown ) {
561
573
this . throwOnNetworkError ( err )
562
574
563
575
this . #validationErrors. set ( id , UnknownError . cast ( err ) )
564
576
getLogger ( ) . info ( `auth: Handling validation error of connection: ${ id } ` )
565
- return this . updateConnectionState ( id , 'invalid' )
566
577
}
567
578
568
579
private async getConnectionFromStoreEntry ( [ id , profile ] : readonly [ Connection [ 'id' ] , StoredProfile < Profile > ] ) {
@@ -699,7 +710,8 @@ export class Auth implements AuthService, ConnectionManager {
699
710
}
700
711
701
712
private readonly authenticate = keyedDebounce ( this . _authenticate . bind ( this ) )
702
- private async _authenticate < T > ( id : Connection [ 'id' ] , callback : ( ) => Promise < T > ) : Promise < T > {
713
+ private async _authenticate < T > ( id : Connection [ 'id' ] , callback : ( ) => Promise < T > , invalidate ?: boolean ) : Promise < T > {
714
+ const originalState = this . getConnectionState ( { id } ) ?? 'unauthenticated'
703
715
await this . updateConnectionState ( id , 'authenticating' )
704
716
705
717
try {
@@ -709,6 +721,7 @@ export class Auth implements AuthService, ConnectionManager {
709
721
return result
710
722
} catch ( err ) {
711
723
await this . handleSsoTokenError ( id , err )
724
+ await this . updateConnectionState ( id , invalidate ? 'invalid' : originalState )
712
725
throw err
713
726
}
714
727
}
0 commit comments