diff --git a/extensions/azurecore/src/account-provider/auths/azureAuth.ts b/extensions/azurecore/src/account-provider/auths/azureAuth.ts index d94901cc60..48d4626725 100644 --- a/extensions/azurecore/src/account-provider/auths/azureAuth.ts +++ b/extensions/azurecore/src/account-provider/auths/azureAuth.ts @@ -27,7 +27,7 @@ import { AzureAuthError } from './azureAuthError'; import { AccountInfo, AuthenticationResult, InteractionRequiredAuthError, PublicClientApplication } from '@azure/msal-node'; import { HttpClient } from './httpClient'; import { getProxyEnabledHttpClient } from '../../utils'; - +import { errorToPromptFailedResult } from './networkUtils'; const localize = nls.loadMessageBundle(); export abstract class AzureAuth implements vscode.Disposable { @@ -146,22 +146,14 @@ export abstract class AzureAuth implements vscode.Disposable { } Logger.error(ex.originalMessageAndException); } else { - const message = ex.errorMessage || ex.message; - if (message) { - loginComplete?.reject(new AzureAuthError(message, message, undefined)); - return { - canceled: false, - errorCode: ex.errorCode, - errorMessage: message - }; + const promptFailedResult = errorToPromptFailedResult(ex); + if (promptFailedResult.errorMessage) { + loginComplete?.reject(new AzureAuthError(promptFailedResult.errorMessage, promptFailedResult.errorMessage, undefined)); + return promptFailedResult; } Logger.error(ex); } - return { - canceled: false, - errorCode: ex.errorCode, - errorMessage: ex.errorMessage || ex.message - }; + return errorToPromptFailedResult(ex); } } @@ -373,12 +365,7 @@ export abstract class AzureAuth implements vscode.Disposable { if (e.name === 'ClientAuthError') { Logger.verbose('[ClientAuthError] Failed to silently acquire token'); } - return { - canceled: false, - name: e.name, - errorCode: e.errorCode, - errorMessage: e.errorMessage || e.message - } + return errorToPromptFailedResult(e); } } } @@ -610,10 +597,10 @@ export abstract class AzureAuth implements vscode.Disposable { Logger.error('No access token found'); return undefined; } - const accessToken: AccessToken = JSON.parse(accessTokenString); + const accessToken: AccessToken = JSON.parse(accessTokenString) as AccessToken; let refreshToken: RefreshToken | undefined = undefined; if (refreshTokenString) { - refreshToken = JSON.parse(refreshTokenString); + refreshToken = JSON.parse(refreshTokenString) as RefreshToken; } Logger.piiSanitized('GetSavedToken ', [{ name: 'access', objOrArray: accessToken }, { name: 'refresh', objOrArray: refreshToken }], [], `expiresOn=${expiresOn}`); return { diff --git a/extensions/azurecore/src/account-provider/auths/httpClient.ts b/extensions/azurecore/src/account-provider/auths/httpClient.ts index d3fa0c60b6..6dff9f328e 100644 --- a/extensions/azurecore/src/account-provider/auths/httpClient.ts +++ b/extensions/azurecore/src/account-provider/auths/httpClient.ts @@ -8,7 +8,7 @@ import { INetworkModule, NetworkRequestOptions, NetworkResponse } from '@azure/m import * as http from 'http'; import * as https from 'https'; import { TextEncoder } from 'util'; -import { NetworkUtils } from './networkUtils'; +import { getNetworkResponse, urlToHttpOptions } from './networkUtils'; /** * http methods @@ -247,7 +247,7 @@ const networkRequestViaProxy = ( }); const parsedHeaders = Object.fromEntries(entries) as Record; - const networkResponse = NetworkUtils.getNetworkResponse( + const networkResponse = getNetworkResponse( parsedHeaders, parseBody(httpStatusCode, statusMessage, parsedHeaders, body) as T, httpStatusCode @@ -293,7 +293,7 @@ const networkRequestViaHttps = ( let customOptions: https.RequestOptions = { method: httpMethod, headers: optionHeaders, - ...NetworkUtils.urlToHttpOptions(url) + ...urlToHttpOptions(url) }; if (timeout) { @@ -343,7 +343,7 @@ const networkRequestViaHttps = ( const dataBody = Buffer.concat([...data]).toString(); const parsedHeaders = headers as Record; - const networkResponse = NetworkUtils.getNetworkResponse( + const networkResponse = getNetworkResponse( parsedHeaders, parseBody(statusCode, statusMessage, parsedHeaders, dataBody) as T, statusCode diff --git a/extensions/azurecore/src/account-provider/auths/networkUtils.ts b/extensions/azurecore/src/account-provider/auths/networkUtils.ts index 2ba57d1e1e..fd1ec8b70f 100644 --- a/extensions/azurecore/src/account-provider/auths/networkUtils.ts +++ b/extensions/azurecore/src/account-provider/auths/networkUtils.ts @@ -3,41 +3,54 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as azdata from 'azdata'; import { NetworkResponse } from '@azure/msal-common'; import * as https from 'https'; -export class NetworkUtils { - static getNetworkResponse(headers: Record, body: Body, statusCode: number): NetworkResponse { - return { - headers: headers, - body: body, - status: statusCode - }; - } - - /* - * Utility function that converts a URL object into an ordinary options object as expected by the - * http.request and https.request APIs. - */ - static urlToHttpOptions(url: URL): https.RequestOptions { - const options: https.RequestOptions & Partial> = { - protocol: url.protocol, - hostname: url.hostname && url.hostname.startsWith('[') ? - url.hostname.slice(1, -1) : - url.hostname, - hash: url.hash, - search: url.search, - pathname: url.pathname, - path: `${url.pathname || ''}${url.search || ''}`, - href: url.href - }; - if (url.port !== '') { - options.port = Number(url.port); - } - if (url.username || url.password) { - options.auth = `${decodeURIComponent(url.username)}:${decodeURIComponent(url.password)}`; - } - return options; - } +export function getNetworkResponse(headers: Record, body: Body, statusCode: number): NetworkResponse { + return { + headers: headers, + body: body, + status: statusCode + }; +} + +/* + * Utility function that converts a URL object into an ordinary options object as expected by the + * http.request and https.request APIs. + */ +export function urlToHttpOptions(url: URL): https.RequestOptions { + const options: https.RequestOptions & Partial> = { + protocol: url.protocol, + hostname: url.hostname && url.hostname.startsWith('[') ? + url.hostname.slice(1, -1) : + url.hostname, + hash: url.hash, + search: url.search, + pathname: url.pathname, + path: `${url.pathname || ''}${url.search || ''}`, + href: url.href + }; + if (url.port !== '') { + options.port = Number(url.port); + } + if (url.username || url.password) { + options.auth = `${decodeURIComponent(url.username)}:${decodeURIComponent(url.password)}`; + } + return options; +} + +/** + * Takes an error and converts it into a PromptFailedResult object with data from the original error about the failure + * @param err The error to convert into a PromptFailedResult + * @returns The PromptFailedResult object + */ +export function errorToPromptFailedResult(err: any): azdata.PromptFailedResult { + return { + canceled: false, + name: err.name as string, + errorCode: err.errorCode as string, + errorMessage: err.errorMessage as string || err.message as string + }; } diff --git a/extensions/azurecore/src/azureResource/utils.ts b/extensions/azurecore/src/azureResource/utils.ts index acb511e662..2f6e912a09 100644 --- a/extensions/azurecore/src/azureResource/utils.ts +++ b/extensions/azurecore/src/azureResource/utils.ts @@ -260,7 +260,7 @@ export async function runResourceQuery