Skip to content

Commit 0fc1845

Browse files
Merge pull request #3306 from nkomonen-amazon/builderIdLoginButton
fix(codecatalyst): No solution for 'connection is invalid or expired'
2 parents 944a20a + 1b1bc89 commit 0fc1845

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

src/codecatalyst/commands.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ import { DevEnvironmentId, getConnectedDevEnv, openDevEnv } from './model'
1818
import { showConfigureDevEnv } from './vue/configure/backend'
1919
import { showCreateDevEnv } from './vue/create/backend'
2020
import { CancellationError } from '../shared/utilities/timeoutUtils'
21-
import { ToolkitError } from '../shared/errors'
21+
import { ToolkitError, errorCode } from '../shared/errors'
2222
import { telemetry } from '../shared/telemetry/telemetry'
2323
import { showConfirmationMessage } from '../shared/utilities/messages'
2424
import { AccountStatus } from '../shared/telemetry/telemetryClient'
2525
import { CreateDevEnvironmentRequest, UpdateDevEnvironmentRequest } from 'aws-sdk/clients/codecatalyst'
26+
import { Auth, SsoConnection } from '../credentials/auth'
2627

2728
/** "List CodeCatalyst Commands" command. */
2829
export async function listCommands(): Promise<void> {
@@ -135,13 +136,43 @@ function createClientInjector(authProvider: CodeCatalystAuthenticationProvider):
135136

136137
await authProvider.restore()
137138
const conn = authProvider.activeConnection ?? (await authProvider.promptNotConnected())
138-
const client = await createClient(conn)
139+
const validatedConn = await validateConnection(conn, authProvider.auth)
140+
const client = await createClient(validatedConn)
139141
telemetry.record({ userId: client.identity.id })
140142

141143
return command(client, ...args)
142144
}
143145
}
144146

147+
/**
148+
* Returns a connection that is ensured to be authenticated.
149+
*
150+
* Provides the user the ability to re-authenticate if needed,
151+
* otherwise throwing an error.
152+
*/
153+
async function validateConnection(conn: SsoConnection, auth: Auth): Promise<SsoConnection> {
154+
if (auth.getConnectionState(conn) === 'valid') {
155+
return conn
156+
}
157+
158+
// Have user try to log in
159+
const loginMessage = localize('aws.auth.invalidConnection', 'Connection is invalid or expired, login again?')
160+
const result = await vscode.window.showErrorMessage(loginMessage, 'Login')
161+
162+
if (result !== 'Login') {
163+
throw new ToolkitError('User cancelled login.', { cancelled: true, code: errorCode.invalidConnection })
164+
}
165+
166+
conn = await auth.reauthenticate(conn)
167+
168+
// Log in attempt failed
169+
if (auth.getConnectionState(conn) !== 'valid') {
170+
throw new ToolkitError('Login failed.', { code: errorCode.invalidConnection })
171+
}
172+
173+
return conn
174+
}
175+
145176
function createCommandDecorator(commands: CodeCatalystCommands): CommandDecorator {
146177
return command =>
147178
(...args) =>

src/credentials/auth.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { Commands } from '../shared/vscode/commands2'
1717
import { createQuickPick, DataQuickPickItem, showQuickPick } from '../shared/ui/pickerPrompter'
1818
import { isValidResponse } from '../shared/wizards/wizard'
1919
import { CancellationError } from '../shared/utilities/timeoutUtils'
20-
import { formatError, ToolkitError, UnknownError } from '../shared/errors'
20+
import { errorCode, formatError, ToolkitError, UnknownError } from '../shared/errors'
2121
import { getCache } from './sso/cache'
2222
import { createFactoryFunction, Mutable } from '../shared/utilities/tsUtils'
2323
import { builderIdStartUrl, SsoToken } from './sso/model'
@@ -676,7 +676,7 @@ export class Auth implements AuthService, ConnectionManager {
676676

677677
if (previousState === 'invalid') {
678678
throw new ToolkitError('Connection is invalid or expired. Try logging in again.', {
679-
code: 'InvalidConnection',
679+
code: errorCode.invalidConnection,
680680
cause: this.#validationErrors.get(id),
681681
})
682682
}
@@ -687,7 +687,7 @@ export class Auth implements AuthService, ConnectionManager {
687687
if (resp !== localizedText.yes) {
688688
throw new ToolkitError('User cancelled login', {
689689
cancelled: true,
690-
code: 'InvalidConnection',
690+
code: errorCode.invalidConnection,
691691
cause: this.#validationErrors.get(id),
692692
})
693693
}

src/shared/errors.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ import { Result } from './telemetry/telemetry'
1111
import { CancellationError } from './utilities/timeoutUtils'
1212
import { isNonNullable } from './utilities/tsUtils'
1313

14+
export const errorCode = {
15+
invalidConnection: 'InvalidConnection',
16+
}
17+
1418
export interface ErrorInformation {
1519
/**
1620
* Error names are optional, but if provided they should be generic yet self-explanatory.

0 commit comments

Comments
 (0)