From c04b8af1d281d8a16ff680563f7f900ca44dc3da Mon Sep 17 00:00:00 2001 From: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Thu, 27 Apr 2023 20:44:22 -0700 Subject: [PATCH] Prompt user to refresh account credentials for AADSTS70043 and AADSTS50173 error codes (#22853) --- .../src/account-provider/auths/azureAuth.ts | 16 +++++++++++++--- extensions/azurecore/src/constants.ts | 13 +++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/extensions/azurecore/src/account-provider/auths/azureAuth.ts b/extensions/azurecore/src/account-provider/auths/azureAuth.ts index df25fe22ae..a9c4c270f5 100644 --- a/extensions/azurecore/src/account-provider/auths/azureAuth.ts +++ b/extensions/azurecore/src/account-provider/auths/azureAuth.ts @@ -24,7 +24,7 @@ import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; import { Logger } from '../../utils/Logger'; import * as qs from 'qs'; import { AzureAuthError } from './azureAuthError'; -import { AccountInfo, AuthenticationResult, InteractionRequiredAuthError, PublicClientApplication } from '@azure/msal-node'; +import { AccountInfo, AuthError, AuthenticationResult, InteractionRequiredAuthError, PublicClientApplication } from '@azure/msal-node'; import { HttpClient } from './httpClient'; import { getProxyEnabledHttpClient, getTenantIgnoreList, updateTenantIgnoreList } from '../../utils'; import { errorToPromptFailedResult } from './networkUtils'; @@ -365,7 +365,7 @@ export abstract class AzureAuth implements vscode.Disposable { return await this.clientApplication.acquireTokenSilent(tokenRequest); } catch (e) { Logger.error('Failed to acquireTokenSilent', e); - if (e instanceof InteractionRequiredAuthError) { + if (e instanceof AuthError && this.accountNeedsRefresh(e)) { // build refresh token request const tenant: Tenant = { id: tenantId, @@ -632,7 +632,6 @@ export abstract class AzureAuth implements vscode.Disposable { } //#endregion - //#region interaction handling public async handleInteractionRequiredMsal(tenant: Tenant, resource: Resource): Promise { const shouldOpen = await this.askUserForInteraction(tenant, resource); @@ -654,6 +653,17 @@ export abstract class AzureAuth implements vscode.Disposable { return undefined; } + /** + * Determines whether the account needs to be refreshed based on received error instance + * and STS error codes from errorMessage. + * @param error AuthError instance + */ + private accountNeedsRefresh(error: AuthError): boolean { + return error instanceof InteractionRequiredAuthError + || error.errorMessage.includes(Constants.AADSTS70043) + || error.errorMessage.includes(Constants.AADSTS50173); + } + /** * Asks the user if they would like to do the interaction based authentication as required by OAuth2 * @param tenant diff --git a/extensions/azurecore/src/constants.ts b/extensions/azurecore/src/constants.ts index 8d64ba4ee2..2f1e3dbdb8 100644 --- a/extensions/azurecore/src/constants.ts +++ b/extensions/azurecore/src/constants.ts @@ -78,6 +78,19 @@ export const LocalCacheSuffix = '.local'; export const LockFileSuffix = '.lockfile'; +/////// MSAL ERROR CODES, ref: https://learn.microsoft.com/en-us/azure/active-directory/develop/reference-aadsts-error-codes +/** + * The refresh token has expired or is invalid due to sign-in frequency checks by conditional access. + * The token was issued on {issueDate} and the maximum allowed lifetime for this request is {time}. + */ +export const AADSTS70043 = 'AADSTS70043'; +/** + * FreshTokenNeeded - The provided grant has expired due to it being revoked, and a fresh auth token is needed. + * Either an admin or a user revoked the tokens for this user, causing subsequent token refreshes to fail and + * require reauthentication. Have the user sign in again. + */ +export const AADSTS50173 = 'AADSTS50173'; + export enum BuiltInCommands { SetContext = 'setContext' }