Skip to content

Commit e58a425

Browse files
committed
fix(amazonq): handle existing Flare connection when migrating SSO connections
1 parent 7983fc1 commit e58a425

File tree

2 files changed

+88
-43
lines changed

2 files changed

+88
-43
lines changed

packages/amazonq/test/unit/codewhisperer/util/authUtil.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ describe('AuthUtil', async function () {
225225
})
226226

227227
describe('migrateSsoConnectionToLsp', function () {
228+
let mockLspAuth: any
228229
let memento: any
229230
let cacheDir: string
230231
let fromRegistrationFile: string
@@ -249,6 +250,9 @@ describe('AuthUtil', async function () {
249250

250251
sinon.stub(mementoUtils, 'getEnvironmentSpecificMemento').returns(memento)
251252
sinon.stub(cache, 'getCacheDir').returns(cacheDir)
253+
254+
mockLspAuth = (auth as any).lspAuth
255+
mockLspAuth.getSsoToken.resolves(undefined)
252256

253257
fromTokenFile = cache.getTokenCacheFile(cacheDir, 'profile1')
254258
const registrationKey = {
@@ -269,6 +273,27 @@ describe('AuthUtil', async function () {
269273
sinon.restore()
270274
})
271275

276+
it('skips migration if LSP token exists', async function () {
277+
memento.get.returns({ profile1: validProfile })
278+
mockLspAuth.getSsoToken.resolves({ token: 'valid-token' })
279+
280+
await auth.migrateSsoConnectionToLsp('test-client')
281+
282+
assert.ok(memento.update.calledWith('auth.profiles', undefined))
283+
assert.ok(!auth.session.updateProfile?.called)
284+
})
285+
286+
it('proceeds with migration if LSP token check throws', async function () {
287+
memento.get.returns({ profile1: validProfile })
288+
mockLspAuth.getSsoToken.rejects(new Error('Token check failed'))
289+
const updateProfileStub = sinon.stub((auth as any).session, 'updateProfile').resolves()
290+
291+
await auth.migrateSsoConnectionToLsp('test-client')
292+
293+
assert.ok(updateProfileStub.calledOnce)
294+
assert.ok(memento.update.calledWith('auth.profiles', undefined))
295+
})
296+
272297
it('migrates valid SSO connection', async function () {
273298
memento.get.returns({ profile1: validProfile })
274299

packages/core/src/codewhisperer/util/authUtil.ts

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { getEnvironmentSpecificMemento } from '../../shared/utilities/mementos'
3939
import { getCacheDir, getFlareCacheFileName, getRegistrationCacheFile, getTokenCacheFile } from '../../auth/sso/cache'
4040
import { notifySelectDeveloperProfile } from '../region/utils'
4141
import { once } from '../../shared/utilities/functionUtils'
42+
import { CancellationTokenSource, SsoTokenSourceKind } from '@aws/language-server-runtimes/server-interface'
4243

4344
const localize = nls.loadMessageBundle()
4445

@@ -402,58 +403,77 @@ export class AuthUtil implements IAuthProvider {
402403

403404
if (!profiles) {
404405
return
405-
} else {
406-
getLogger().info(`codewhisperer: checking for old SSO connections`)
407-
for (const [id, p] of Object.entries(profiles)) {
408-
if (p.type === 'sso' && hasExactScopes(p.scopes ?? [], amazonQScopes)) {
409-
toImport = p
410-
profileId = id
411-
if (p.metadata.connectionState === 'valid') {
412-
break
413-
}
414-
}
406+
}
407+
408+
try {
409+
// Try go get token from LSP auth. If available, skip migration and delete old auth profile
410+
const token = await this.lspAuth.getSsoToken(
411+
{
412+
kind: SsoTokenSourceKind.IamIdentityCenter,
413+
profileName: this.profileName,
414+
},
415+
false,
416+
new CancellationTokenSource().token
417+
)
418+
if (token) {
419+
getLogger().info(`codewhisperer: existing LSP auth connection found. Skipping migration`)
420+
await memento.update(key, undefined)
421+
return
415422
}
423+
} catch {
424+
getLogger().info(`codewhisperer: unable to get token from LSP auth, proceeding migration`)
425+
}
416426

417-
if (toImport && profileId) {
418-
getLogger().info(`codewhisperer: migrating SSO connection to LSP identity server...`)
419-
420-
const registrationKey = {
421-
startUrl: toImport.startUrl,
422-
region: toImport.ssoRegion,
423-
scopes: amazonQScopes,
427+
getLogger().info(`codewhisperer: checking for old SSO connections`)
428+
for (const [id, p] of Object.entries(profiles)) {
429+
if (p.type === 'sso' && hasExactScopes(p.scopes ?? [], amazonQScopes)) {
430+
toImport = p
431+
profileId = id
432+
if (p.metadata.connectionState === 'valid') {
433+
break
424434
}
435+
}
436+
}
425437

426-
await this.session.updateProfile(registrationKey)
427-
428-
const cacheDir = getCacheDir()
438+
if (toImport && profileId) {
439+
getLogger().info(`codewhisperer: migrating SSO connection to LSP identity server...`)
429440

430-
const fromRegistrationFile = getRegistrationCacheFile(cacheDir, registrationKey)
431-
const toRegistrationFile = path.join(
432-
cacheDir,
433-
getFlareCacheFileName(
434-
JSON.stringify({
435-
region: toImport.ssoRegion,
436-
startUrl: toImport.startUrl,
437-
tool: clientName,
438-
})
439-
)
440-
)
441+
const registrationKey = {
442+
startUrl: toImport.startUrl,
443+
region: toImport.ssoRegion,
444+
scopes: amazonQScopes,
445+
}
441446

442-
const fromTokenFile = getTokenCacheFile(cacheDir, profileId)
443-
const toTokenFile = path.join(cacheDir, getFlareCacheFileName(this.profileName))
447+
await this.session.updateProfile(registrationKey)
444448

445-
try {
446-
await fs.rename(fromRegistrationFile, toRegistrationFile)
447-
await fs.rename(fromTokenFile, toTokenFile)
448-
getLogger().debug('Successfully renamed registration and token files')
449-
} catch (err) {
450-
getLogger().error(`Failed to rename files during migration: ${err}`)
451-
throw err
452-
}
449+
const cacheDir = getCacheDir()
453450

454-
await memento.update(key, undefined)
455-
getLogger().info(`codewhisperer: successfully migrated SSO connection to LSP identity server`)
451+
const fromRegistrationFile = getRegistrationCacheFile(cacheDir, registrationKey)
452+
const toRegistrationFile = path.join(
453+
cacheDir,
454+
getFlareCacheFileName(
455+
JSON.stringify({
456+
region: toImport.ssoRegion,
457+
startUrl: toImport.startUrl,
458+
tool: clientName,
459+
})
460+
)
461+
)
462+
463+
const fromTokenFile = getTokenCacheFile(cacheDir, profileId)
464+
const toTokenFile = path.join(cacheDir, getFlareCacheFileName(this.profileName))
465+
466+
try {
467+
await fs.rename(fromRegistrationFile, toRegistrationFile)
468+
await fs.rename(fromTokenFile, toTokenFile)
469+
getLogger().debug('Successfully renamed registration and token files')
470+
} catch (err) {
471+
getLogger().error(`Failed to rename files during migration: ${err}`)
472+
throw err
456473
}
474+
475+
getLogger().info(`codewhisperer: successfully migrated SSO connection to LSP identity server`)
476+
await memento.update(key, undefined)
457477
}
458478
}
459479
}

0 commit comments

Comments
 (0)