Skip to content

Commit 11723eb

Browse files
authored
fix(CodeWhisperer): auto-refresh credentials on Cloud9 #2727
Problem The Toolkit credentials system does not use a file watcher for detecting credential changes. This specifically affects CodeWhisperer as they never emit an `ExpiredTokenException` which would otherwise trigger a refresh. ## Solution Force a refresh on errors that are obviously due to expired credentials. We heavily restrict the exact circumstances that this code path can be executed to mitigate risk. Soon-ish we'll have a file watcher so we can drop a lot of these workarounds.
1 parent 53421f2 commit 11723eb

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "'security token expired' errors when using CodeWhisperer in Cloud9 with managed credentials"
4+
}

src/codewhisperer/client/codewhisperer.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ import { isCloud9 } from '../../shared/extensionUtilities'
1414
import { CodeWhispererSettings } from '../util/codewhispererSettings'
1515
import { getCognitoCredentials } from '../util/cognitoIdentity'
1616
import { PromiseResult } from 'aws-sdk/lib/request'
17+
import { getLogger } from '../../shared/logger'
18+
import { throttle } from 'lodash'
19+
20+
const refreshCredentials = throttle(() => {
21+
getLogger().verbose('codewhisperer: invalidating expired credentials')
22+
globals.awsContext.credentialsShim?.refresh()
23+
}, 60000)
1724

1825
export type ProgrammingLanguage = Readonly<CodeWhispererClient.ProgrammingLanguage>
1926
export type FileContext = Readonly<CodeWhispererClient.FileContext>
@@ -61,6 +68,20 @@ export class DefaultCodeWhispererClient {
6168
req.httpRequest.headers['x-amzn-codewhisperer-optout'] = `${isOptedOut}`
6269
})
6370
}
71+
72+
// This logic is for backward compatability with legacy SDK v2 behavior for refreshing
73+
// credentials. Once the Toolkit adds a file watcher for credentials it won't be needed.
74+
if (isCloud9() && req.operation !== 'getAccessToken') {
75+
req.on('retry', resp => {
76+
if (
77+
resp.error?.code === 'AccessDeniedException' &&
78+
resp.error.message.match(/expired/i)
79+
) {
80+
refreshCredentials()
81+
resp.error.retryable = true
82+
}
83+
})
84+
}
6485
},
6586
],
6687
} as ServiceOptions,

0 commit comments

Comments
 (0)