@@ -30,6 +30,8 @@ import { builderIdStartUrl, internalStartUrl } from '../../auth/sso/constants'
3030import { VSCODE_EXTENSION_ID } from '../../shared/extensions'
3131import { RegionProfileManager } from '../region/regionProfileManager'
3232import { AuthFormId } from '../../login/webview/vue/types'
33+ import { notifySelectDeveloperProfile } from '../region/utils'
34+ import { once } from '../../shared/utilities/functionUtils'
3335
3436const localize = nls . loadMessageBundle ( )
3537
@@ -91,9 +93,31 @@ export class AuthUtil implements IAuthProvider {
9193 return this . session . loginType === LoginTypes . SSO
9294 }
9395
96+ /**
97+ * HACK: Ideally we'd put {@link notifySelectDeveloperProfile} in to {@link restore}.
98+ * But because {@link refreshState} is only called if !isConnected, we cannot do it since
99+ * {@link notifySelectDeveloperProfile} needs {@link refreshState} to run so it can set
100+ * the Bearer Token in the LSP first.
101+ */
102+ didStartSignedIn = false
103+
94104 async restore ( ) {
95105 await this . session . restore ( )
96- if ( ! this . isConnected ( ) ) {
106+ this . didStartSignedIn = this . isConnected ( )
107+
108+ // HACK: We noticed that if calling `refreshState()` here when the user was already signed in, something broke.
109+ // So as a solution we only call it if they were not already signed in.
110+ //
111+ // But in the case where a user was already signed in, we allow `session.restore()` to trigger `refreshState()` through
112+ // event emitters.
113+ // This is unoptimal since `refreshState()` should be able to be called multiple times and still work.
114+ //
115+ // Because of this edge case, when `restore()` is called we cannot assume all Auth is setup when this function returns,
116+ // since we may still be waiting on the event emitter to trigger the expected functions.
117+ //
118+ // TODO: Figure out why removing the if statement below causes things to break. Maybe we just need to
119+ // promisify the call and any subsequent callers will not make a redundant call.
120+ if ( ! this . didStartSignedIn ) {
97121 await this . refreshState ( )
98122 }
99123 }
@@ -257,20 +281,24 @@ export class AuthUtil implements IAuthProvider {
257281
258282 private async refreshState ( state = this . getAuthState ( ) ) {
259283 if ( state === 'expired' || state === 'notConnected' ) {
284+ this . lspAuth . deleteBearerToken ( )
260285 if ( this . isIdcConnection ( ) ) {
261286 await this . regionProfileManager . invalidateProfile ( this . regionProfileManager . activeRegionProfile ?. arn )
262287 await this . regionProfileManager . clearCache ( )
263288 }
264- this . lspAuth . deleteBearerToken ( )
265289 }
266290 if ( state === 'connected' ) {
291+ const bearerTokenParams = ( await this . session . getToken ( ) ) . updateCredentialsParams
292+ await this . lspAuth . updateBearerToken ( bearerTokenParams )
293+
267294 if ( this . isIdcConnection ( ) ) {
268295 await this . regionProfileManager . restoreProfileSelection ( )
269296 }
270- const bearerTokenParams = ( await this . session . getToken ( ) ) . updateCredentialsParams
271- await this . lspAuth . updateBearerToken ( bearerTokenParams )
272297 }
273298
299+ // regardless of state, send message at startup if user needs to select a Developer Profile
300+ void this . tryNotifySelectDeveloperProfile ( )
301+
274302 vsCodeState . isFreeTierLimitReached = false
275303 await this . setVscodeContextProps ( state )
276304 await Promise . all ( [
@@ -283,6 +311,12 @@ export class AuthUtil implements IAuthProvider {
283311 }
284312 }
285313
314+ private tryNotifySelectDeveloperProfile = once ( async ( ) => {
315+ if ( this . regionProfileManager . requireProfileSelection ( ) && this . didStartSignedIn ) {
316+ await notifySelectDeveloperProfile ( )
317+ }
318+ } )
319+
286320 async getTelemetryMetadata ( ) : Promise < TelemetryMetadata > {
287321 if ( ! this . isConnected ( ) ) {
288322 return {
0 commit comments