Handle multiple matching tokens error (#23441)

Surfaces when fetching subscriptions
This commit is contained in:
Cheena Malhotra
2023-06-27 10:48:10 -07:00
committed by GitHub
parent 92935429ca
commit fcb56da720
3 changed files with 66 additions and 43 deletions

View File

@@ -332,13 +332,15 @@ export abstract class AzureAuth implements vscode.Disposable {
// Resource endpoint must end with '/' to form a valid scope for MSAL token request. // Resource endpoint must end with '/' to form a valid scope for MSAL token request.
const endpoint = resource.endpoint.endsWith('/') ? resource.endpoint : resource.endpoint + '/'; const endpoint = resource.endpoint.endsWith('/') ? resource.endpoint : resource.endpoint + '/';
let account: AccountInfo | null;
let newScope;
let account: AccountInfo | null = await this.getAccountFromMsalCache(accountId); try {
account = await this.getAccountFromMsalCache(accountId);
if (!account) { if (!account) {
Logger.error('Error: Could not fetch account when acquiring token'); Logger.error('Error: Could not fetch account when acquiring token');
throw new Error(localize('msal.accountNotFoundError', `Unable to find account info when acquiring token.`)); throw new Error(localize('msal.accountNotFoundError', `Unable to find account info when acquiring token, please remove account and add again.`));
} }
let newScope;
if (resource.azureResourceId === azdata.AzureResource.ResourceManagement) { if (resource.azureResourceId === azdata.AzureResource.ResourceManagement) {
newScope = [`${endpoint}user_impersonation`]; newScope = [`${endpoint}user_impersonation`];
} else { } else {
@@ -373,6 +375,10 @@ export abstract class AzureAuth implements vscode.Disposable {
return errorToPromptFailedResult(e); return errorToPromptFailedResult(e);
} }
} }
} catch (error) {
Logger.error(`[ClientAuthError] Failed to find account: ${error}`);
return errorToPromptFailedResult(error);
}
} }
public async getAccountFromMsalCache(accountId: string): Promise<AccountInfo | null> { public async getAccountFromMsalCache(accountId: string): Promise<AccountInfo | null> {
@@ -904,12 +910,16 @@ export abstract class AzureAuth implements vscode.Disposable {
private async deleteAccountCacheMsal(accountKey: azdata.AccountKey): Promise<void> { private async deleteAccountCacheMsal(accountKey: azdata.AccountKey): Promise<void> {
const tokenCache = this.clientApplication.getTokenCache(); const tokenCache = this.clientApplication.getTokenCache();
try {
let msalAccount: AccountInfo | null = await this.getAccountFromMsalCache(accountKey.accountId); let msalAccount: AccountInfo | null = await this.getAccountFromMsalCache(accountKey.accountId);
if (!msalAccount) { if (!msalAccount) {
Logger.error(`MSAL: Unable to find account ${accountKey.accountId} for removal`); Logger.error(`MSAL: Unable to find account ${accountKey.accountId} for removal`);
throw Error(`Unable to find account ${accountKey.accountId}`); throw Error(`Unable to find account ${accountKey.accountId}`);
} }
await tokenCache.removeAccount(msalAccount); await tokenCache.removeAccount(msalAccount);
} catch (error) {
Logger.error(`[ClientAuthError] Failed to find account: ${error}`);
}
await this.msalCacheProvider.clearAccountFromLocalCache(accountKey.accountId); await this.msalCacheProvider.clearAccountFromLocalCache(accountKey.accountId);
} }

View File

@@ -15,6 +15,7 @@ import { Logger } from '../../utils/Logger';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import { TenantIgnoredError } from '../../utils/TenantIgnoredError'; import { TenantIgnoredError } from '../../utils/TenantIgnoredError';
import { multiple_matching_tokens_error } from '../../constants';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
export class AzureResourceSubscriptionService implements IAzureResourceSubscriptionService { export class AzureResourceSubscriptionService implements IAzureResourceSubscriptionService {
@@ -52,8 +53,12 @@ export class AzureResourceSubscriptionService implements IAzureResourceSubscript
} }
} catch (error) { } catch (error) {
if (!account.isStale && !(error instanceof TenantIgnoredError)) { if (!account.isStale && !(error instanceof TenantIgnoredError)) {
const errorMsg = localize('azure.resource.tenantSubscriptionsError', "Failed to get subscriptions for account {0} (tenant '{1}'). {2}", account.displayInfo.displayName, tenantId, AzureResourceErrorMessageUtil.getErrorMessage(error)); const msg = AzureResourceErrorMessageUtil.getErrorMessage(error);
Logger.error(`Failed to get subscriptions for account ${account.displayInfo.displayName} (tenant '${tenantId}'). ${AzureResourceErrorMessageUtil.getErrorMessage(error)}`); let errorMsg = localize('azure.resource.tenantSubscriptionsError', "Failed to get subscriptions for account {0} (tenant '{1}'). {2}", account.displayInfo.displayName, tenantId, msg);
if (msg.includes(multiple_matching_tokens_error)) {
errorMsg = errorMsg.concat(` To resolve this error, please clear token cache, and refresh account credentials.`);
}
Logger.error(`Failed to get subscriptions for account ${account.displayInfo.displayName} (tenant '${tenantId}'). ${msg}`);
errors.push(error); errors.push(error);
void vscode.window.showWarningMessage(errorMsg); void vscode.window.showWarningMessage(errorMsg);
} }

View File

@@ -93,6 +93,14 @@ export const AADSTS70043 = 'AADSTS70043';
*/ */
export const AADSTS50173 = 'AADSTS50173'; export const AADSTS50173 = 'AADSTS50173';
/**
* multiple_matching_tokens error can occur in scenarios when users try to run ADS as different users, reference issue:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/5134
* Error message: multiple_matching_tokens The cache contains multiple tokens satisfying the requirements.
* Call AcquireToken again providing more requirements such as authority or account.
*/
export const multiple_matching_tokens_error = 'multiple_matching_tokens';
export enum BuiltInCommands { export enum BuiltInCommands {
SetContext = 'setContext' SetContext = 'setContext'
} }