Skip to content

Commit 2def22a

Browse files
amazonQ: only add missing scopes intentionally (#4152)
* amazonQ: only add missing scopes intentionally Problem: Before we would always add missing scopes whenever an existing CW user was missing the new scopes for chat. This would be done during the reauthentication process automatically. The issue is that we did not want this and only wanted to add missing Amazon Q/chat scopes when the user intentionally wanted them to be added. Solution: - Don't always add missing scopes during reauthenticate(). Instead use an arg to determine if we should - We will add missing scopes in the Chat "reauthenticate" prompt as well as the Amazon Q node. - Everywhere else will simply reauthenticate without adding new scopes Signed-off-by: nkomonen <[email protected]> * add type to signature Signed-off-by: nkomonen <[email protected]> * add check for invalid arg There is a possibility that addMissingScopes is incorrectly set by vscode, so check and set a default if necessary Signed-off-by: nkomonen <[email protected]> --------- Signed-off-by: nkomonen <[email protected]>
1 parent 56a706d commit 2def22a

File tree

5 files changed

+39
-21
lines changed

5 files changed

+39
-21
lines changed

src/amazonq/auth/controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ export class AuthController {
3030
}
3131

3232
private handleReAuth() {
33-
reconnect.execute(placeholder, amazonQChatSource)
33+
reconnect.execute(placeholder, amazonQChatSource, true)
3434
}
3535
}

src/amazonq/explorer/amazonQChildrenNodes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const switchToAmazonQNode = () =>
5050
*/
5151
export const enableAmazonQNode = () =>
5252
// Simply trigger re-auth to obtain the proper scopes- same functionality as if requested in the chat window.
53-
reconnect.build(placeholder, cwTreeNodeSource).asTreeNode({
53+
reconnect.build(placeholder, cwTreeNodeSource, true).asTreeNode({
5454
label: localize('AWS.amazonq.enable', 'Enable'),
5555
iconPath: getIcon('vscode-debug-start'),
5656
contextValue: 'awsEnableAmazonQ',

src/codewhisperer/commands/basicCommands.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,13 @@ export const selectCustomizationPrompt = Commands.declare(
151151

152152
export const reconnect = Commands.declare(
153153
{ id: 'aws.codewhisperer.reconnect', compositeKey: { 1: 'source' } },
154-
() => async (_: VsCodeCommandArg, source: CodeWhispererSource) => {
155-
await AuthUtil.instance.reauthenticate()
156-
}
154+
() =>
155+
async (_: VsCodeCommandArg, source: CodeWhispererSource, addMissingScopes: boolean = false) => {
156+
if (typeof addMissingScopes !== 'boolean') {
157+
addMissingScopes = false
158+
}
159+
await AuthUtil.instance.reauthenticate(addMissingScopes)
160+
}
157161
)
158162

159163
/** Opens the Add Connections webview with CW highlighted */

src/codewhisperer/util/authUtil.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ export const codeWhispererCoreScopes = [...scopesSsoAccountAccess, ...scopesCode
3636
export const codeWhispererChatScopes = [...codeWhispererCoreScopes, ...scopesCodeWhispererChat]
3737
export const amazonQScopes = [...codeWhispererChatScopes, ...scopesGumby, ...scopesFeatureDev]
3838

39-
export const awsBuilderIdSsoProfile = createBuilderIdProfile(codeWhispererChatScopes)
40-
4139
/**
4240
* "Core" are the CW scopes that existed before the addition of new scopes
4341
* for Amazon Q.
@@ -211,7 +209,7 @@ export class AuthUtil {
211209
let conn = (await this.auth.listConnections()).find(isBuilderIdConnection)
212210

213211
if (!conn) {
214-
conn = await this.auth.createConnection(awsBuilderIdSsoProfile)
212+
conn = await this.auth.createConnection(createBuilderIdProfile(codeWhispererChatScopes))
215213
} else if (!isValidCodeWhispererChatConnection(conn)) {
216214
conn = await this.secondaryAuth.addScopes(conn, codeWhispererChatScopes)
217215
}
@@ -304,23 +302,27 @@ export class AuthUtil {
304302
return connectionExpired
305303
}
306304

307-
public async reauthenticate() {
305+
public async reauthenticate(addMissingScopes: boolean = false) {
308306
try {
309307
if (this.conn?.type !== 'sso') {
310308
return
311309
}
312310

313311
// Edge Case: With the addition of Amazon Q/Chat scopes we may need to add
314-
// the new scopes to existing connections.
315-
if (isBuilderIdConnection(this.conn) && !isValidCodeWhispererChatConnection(this.conn)) {
316-
const conn = await this.secondaryAuth.addScopes(this.conn, codeWhispererChatScopes)
317-
this.secondaryAuth.useNewConnection(conn)
318-
} else if (isIdcSsoConnection(this.conn) && !isValidAmazonQConnection(this.conn)) {
319-
const conn = await this.secondaryAuth.addScopes(this.conn, amazonQScopes)
320-
this.secondaryAuth.useNewConnection(conn)
321-
} else {
322-
await this.auth.reauthenticate(this.conn)
312+
// the new scopes to existing pre-chat connections.
313+
if (addMissingScopes) {
314+
if (isBuilderIdConnection(this.conn) && !isValidCodeWhispererChatConnection(this.conn)) {
315+
const conn = await this.secondaryAuth.addScopes(this.conn, codeWhispererChatScopes)
316+
await this.secondaryAuth.useNewConnection(conn)
317+
return
318+
} else if (isIdcSsoConnection(this.conn) && !isValidAmazonQConnection(this.conn)) {
319+
const conn = await this.secondaryAuth.addScopes(this.conn, amazonQScopes)
320+
await this.secondaryAuth.useNewConnection(conn)
321+
return
322+
}
323323
}
324+
325+
await this.auth.reauthenticate(this.conn)
324326
} catch (err) {
325327
throw ToolkitError.chain(err, 'Unable to authenticate connection')
326328
} finally {

src/test/codewhisperer/util/authUtil.test.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,23 +145,35 @@ describe('AuthUtil', async function () {
145145
assert.strictEqual(auth.getConnectionState(conn), 'valid')
146146
})
147147

148-
it('reauthenticate adds missing CodeWhisperer Chat Builder ID scopes', async function () {
148+
it('reauthenticate does NOT add missing CodeWhisperer scopes if not required to', async function () {
149149
const conn = await auth.createConnection(createBuilderIdProfile({ scopes: codeWhispererCoreScopes }))
150150
await auth.useConnection(conn)
151151

152152
await authUtil.reauthenticate()
153153

154+
assert.strictEqual(authUtil.conn?.type, 'sso')
155+
assert.deepStrictEqual(authUtil.conn?.scopes, codeWhispererCoreScopes)
156+
})
157+
158+
it('reauthenticate adds missing CodeWhisperer Chat Builder ID scopes when explicitly required', async function () {
159+
const conn = await auth.createConnection(createBuilderIdProfile({ scopes: codeWhispererCoreScopes }))
160+
await auth.useConnection(conn)
161+
162+
// method under test
163+
await authUtil.reauthenticate(true)
164+
154165
assert.strictEqual(authUtil.conn?.type, 'sso')
155166
assert.deepStrictEqual(authUtil.conn?.scopes, codeWhispererChatScopes)
156167
})
157168

158-
it('reauthenticate adds missing Amazon Q IdC scopes', async function () {
169+
it('reauthenticate adds missing Amazon Q IdC scopes when explicitly required', async function () {
159170
const conn = await auth.createConnection(
160171
createSsoProfile({ startUrl: enterpriseSsoStartUrl, scopes: codeWhispererCoreScopes })
161172
)
162173
await auth.useConnection(conn)
163174

164-
await authUtil.reauthenticate()
175+
// method under test
176+
await authUtil.reauthenticate(true)
165177

166178
assert.strictEqual(authUtil.conn?.type, 'sso')
167179
assert.deepStrictEqual(authUtil.conn?.scopes, amazonQScopes)

0 commit comments

Comments
 (0)