Skip to content

Commit 509e422

Browse files
authored
Fix the 'Add account' for AlwaysEncrypted sign-in (#21432)
* Fix the 'Add account' for AlwaysEncrypted sign-in * Add a function comment for the null/undefined behavior
1 parent cbe8c85 commit 509e422

2 files changed

Lines changed: 392 additions & 28 deletions

File tree

extensions/mssql/src/controllers/connectionManager.ts

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,33 +2036,43 @@ export default class ConnectionManager {
20362036
private async handleSecurityTokenRequest(
20372037
params: RequestSecurityTokenParams,
20382038
): Promise<RequestSecurityTokenResponse> {
2039-
if (this._keyVaultTokenCache.has(JSON.stringify(params))) {
2040-
const token = this._keyVaultTokenCache.get(JSON.stringify(params));
2041-
const isExpired = AzureController.isTokenExpired(token.expiresOn);
2042-
if (!isExpired) {
2043-
return {
2044-
accountKey: token.key,
2045-
token: token.token,
2046-
};
2047-
} else {
2048-
this._keyVaultTokenCache.delete(JSON.stringify(params));
2039+
try {
2040+
if (this._keyVaultTokenCache.has(JSON.stringify(params))) {
2041+
const token = this._keyVaultTokenCache.get(JSON.stringify(params));
2042+
const isExpired = AzureController.isTokenExpired(token.expiresOn);
2043+
if (!isExpired) {
2044+
return {
2045+
accountKey: token.key,
2046+
token: token.token,
2047+
};
2048+
} else {
2049+
this._keyVaultTokenCache.delete(JSON.stringify(params));
2050+
}
20492051
}
2050-
}
2051-
const account = await this.selectAccount();
2052-
const tenant = await this.selectTenantId(account);
2052+
const account = await this.selectAccount();
2053+
const tenant = await this.selectTenantId(account);
20532054

2054-
const token = await this.azureController.getAccountSecurityToken(
2055-
account,
2056-
tenant,
2057-
getCloudProviderSettings(account.key.providerId).settings.azureKeyVaultResource,
2058-
);
2055+
const token = await this.azureController.getAccountSecurityToken(
2056+
account,
2057+
tenant,
2058+
getCloudProviderSettings(account.key.providerId).settings.azureKeyVaultResource,
2059+
);
20592060

2060-
this._keyVaultTokenCache.set(JSON.stringify(params), token);
2061+
this._keyVaultTokenCache.set(JSON.stringify(params), token);
20612062

2062-
return {
2063-
accountKey: token.key,
2064-
token: token.token,
2065-
};
2063+
return {
2064+
accountKey: token.key,
2065+
token: token.token,
2066+
};
2067+
} catch (error) {
2068+
this._logger.error(`Security token request failed: ${getErrorMessage(error)}`);
2069+
// Return empty response rather than letting the error propagate
2070+
// to STS as a null reference
2071+
return {
2072+
accountKey: "",
2073+
token: "",
2074+
};
2075+
}
20662076
}
20672077

20682078
private async selectAccount(): Promise<IAccount> {
@@ -2074,6 +2084,16 @@ export default class ConnectionManager {
20742084
const quickPickItems = this.createAccountQuickPickItems(accounts, currentAccountId);
20752085
const selectedAccount = await this.showAccountQuickPick(quickPickItems);
20762086

2087+
// eslint-disable-next-line no-restricted-syntax
2088+
if (selectedAccount === null) {
2089+
// User selected "Sign in to Azure" — trigger sign-in and use the new account
2090+
const newAccount = await this.addAccount();
2091+
if (!newAccount) {
2092+
throw new Error(LocalizedConstants.Connection.noAccountSelected);
2093+
}
2094+
return newAccount;
2095+
}
2096+
20772097
if (!selectedAccount) {
20782098
throw new Error(LocalizedConstants.Connection.noAccountSelected);
20792099
}
@@ -2103,30 +2123,47 @@ export default class ConnectionManager {
21032123
return accountItems;
21042124
}
21052125

2126+
/*
2127+
* Shows a quick pick to select an account. Returns the selected account, null if "Sign in to Azure" was selected,
2128+
* or undefined if the quick pick was dismissed.
2129+
* @params items The quick pick items to show
2130+
* @returns The selected account, null if "Sign in to Azure" was selected, or undefined if the quick pick was dismissed
2131+
*/
21062132
private async showAccountQuickPick(
21072133
items: AccountQuickPickItem[],
2108-
): Promise<IAccount | undefined> {
2109-
const account = await new Promise<IAccount | undefined>((resolve, reject) => {
2134+
): Promise<IAccount | null | undefined> {
2135+
const account = await new Promise<IAccount | null | undefined>((resolve, reject) => {
21102136
const quickPick = vscode.window.createQuickPick<AccountQuickPickItem>();
21112137
quickPick.items = items;
21122138
quickPick.placeholder = LocalizedConstants.Connection.SelectAccountForKeyVault;
2139+
let accepted = false;
21132140

21142141
quickPick.onDidAccept(async () => {
21152142
try {
2143+
accepted = true;
21162144
const selectedItem = quickPick.selectedItems[0];
2145+
quickPick.dispose();
21172146
if (!selectedItem) {
21182147
resolve(undefined);
21192148
return;
21202149
}
21212150

21222151
const account = selectedItem.account;
2123-
quickPick.dispose();
2124-
resolve(account);
2152+
// Return null to signal "sign in" was selected (account is undefined on that item)
2153+
resolve(account ?? null); // eslint-disable-line no-restricted-syntax
21252154
} catch (error) {
21262155
quickPick.dispose();
21272156
reject(error);
21282157
}
21292158
});
2159+
2160+
quickPick.onDidHide(() => {
2161+
quickPick.dispose();
2162+
if (!accepted) {
2163+
resolve(undefined);
2164+
}
2165+
});
2166+
21302167
quickPick.show();
21312168
});
21322169
return account;

0 commit comments

Comments
 (0)