From 8816254b11488c2b8141510f82772f538ea30477 Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Wed, 29 Oct 2025 16:18:08 -0700 Subject: [PATCH 01/12] error surfacing changes --- .../src/broker/NativeBrokerPlugin.ts | 39 ++++++++---- .../test/broker/NativeBrokerPlugin.spec.ts | 63 +++++++++++++++++++ lib/msal-common/src/error/AuthError.ts | 6 ++ lib/msal-common/src/error/NativeAuthError.ts | 34 ++++++++++ lib/msal-common/src/exports-common.ts | 1 + 5 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 lib/msal-common/src/error/NativeAuthError.ts diff --git a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts index 445d626c9a..5723919d71 100644 --- a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts +++ b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts @@ -660,46 +660,61 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { const enhancedErrorContext = errorContext ? `${errorContext} (Error Code: ${errorCode}, Tag: ${tagString})` : `(Error Code: ${errorCode}, Tag: ${tagString})`; + + const nativeAuthError = new NativeAuthError( + ErrorStatus[errorStatus], + enhancedErrorContext, + errorCode, + errorTag + ); + + let wrappedError; + switch (errorStatus) { case ErrorStatus.InteractionRequired: case ErrorStatus.AccountUnusable: - return new InteractionRequiredAuthError( + wrappedError = new InteractionRequiredAuthError( ErrorCodes.INTERATION_REQUIRED_ERROR_CODE, enhancedErrorContext ); + break; case ErrorStatus.NoNetwork: case ErrorStatus.NetworkTemporarilyUnavailable: - return createClientAuthError( + wrappedError = createClientAuthError( ClientAuthErrorCodes.noNetworkConnectivity ); + break; case ErrorStatus.ServerTemporarilyUnavailable: - return new ServerError( + wrappedError = new ServerError( ErrorCodes.SERVER_UNAVAILABLE, errorContext ); + break; case ErrorStatus.UserCanceled: - return createClientAuthError( + wrappedError = createClientAuthError( ClientAuthErrorCodes.userCanceled ); + break; case ErrorStatus.AuthorityUntrusted: - return createClientConfigurationError( + wrappedError = createClientConfigurationError( ClientConfigurationErrorCodes.untrustedAuthority ); + break; case ErrorStatus.UserSwitched: // Not an error case, if there's customer demand we can surface this as a response property return null; case ErrorStatus.AccountNotFound: - return createClientAuthError( + wrappedError = createClientAuthError( ClientAuthErrorCodes.noAccountFound ); + break; default: - return new NativeAuthError( - ErrorStatus[errorStatus], - enhancedErrorContext, - errorCode, - errorTag - ); + wrappedError = nativeAuthError; + break; } + + wrappedError.msalNodeRuntimeError = nativeAuthError; + return wrappedError; } throw error; } diff --git a/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts b/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts index 5e48f67a9b..3656bee021 100644 --- a/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts +++ b/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts @@ -2257,6 +2257,69 @@ if (process.platform === "win32") { done(); }); }); + + it("Attaches msalNodeRuntimeError with runtime details to wrapped MSAL.js errors", (done) => { + const testCorrelationId = generateCorrelationId(); + + jest.spyOn( + msalNodeRuntime, + "SignInSilentlyAsync" + ).mockImplementation( + ( + authParams: AuthParameters, + correlationId: string, + callback: (result: AuthResult) => void + ) => { + const result: AuthResult = { + idToken: "", + accessToken: "", + authorizationHeader: "", + rawIdToken: "", + grantedScopes: "", + expiresOn: 0, + isPopAuthorization: false, + account: testMsalRuntimeAccount, + CheckError: () => { + const testError: MsalRuntimeError = { + errorCode: 0, + errorStatus: + ErrorStatus.InteractionRequired, + errorContext: "", + errorTag: 0, + }; + throw testError; + }, + telemetryData: "", + }; + expect(correlationId).toEqual(testCorrelationId); + callback(result); + + return asyncHandle; + } + ); + + const nativeBrokerPlugin = new NativeBrokerPlugin(); + const request: NativeRequest = { + clientId: TEST_CLIENT_ID, + scopes: [], + correlationId: testCorrelationId, + authority: "", + redirectUri: TEST_REDIRECTURI, + }; + + nativeBrokerPlugin + .acquireTokenSilent(request) + .catch((error) => { + expect(error).toBeInstanceOf( + InteractionRequiredAuthError + ); + expect(error.msalNodeRuntimeError).toBeDefined(); + expect(error.msalNodeRuntimeError).toBeInstanceOf( + NativeAuthError + ); + done(); + }); + }); }); }); } else if (process.platform === "darwin") { diff --git a/lib/msal-common/src/error/AuthError.ts b/lib/msal-common/src/error/AuthError.ts index 2e88cec4b6..f66bd39e61 100644 --- a/lib/msal-common/src/error/AuthError.ts +++ b/lib/msal-common/src/error/AuthError.ts @@ -5,6 +5,7 @@ import { Constants } from "../utils/Constants.js"; import * as AuthErrorCodes from "./AuthErrorCodes.js"; +import type { NativeAuthError } from "./NativeAuthError.js"; export { AuthErrorCodes }; export const AuthErrorMessages = { @@ -52,6 +53,11 @@ export class AuthError extends Error { */ correlationId: string; + /** + * Default NativeAuthError from MsalNodeRuntime when broker is enabled + */ + msalNodeRuntimeError?: NativeAuthError; + constructor(errorCode?: string, errorMessage?: string, suberror?: string) { const errorString = errorMessage ? `${errorCode}: ${errorMessage}` diff --git a/lib/msal-common/src/error/NativeAuthError.ts b/lib/msal-common/src/error/NativeAuthError.ts new file mode 100644 index 0000000000..6dcb188fd7 --- /dev/null +++ b/lib/msal-common/src/error/NativeAuthError.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { AuthError } from "./AuthError.js"; + +/** + * Error class for MSAL Runtime errors that preserves detailed broker information + */ +export class NativeAuthError extends AuthError { + /** + * Numeric error code from MSAL Runtime + */ + public statusCode: number; + + /** + * Error tag from MSAL Runtime + */ + public tag: string; + + constructor( + errorStatus: string, + errorContext: string, + errorCode: number, + errorTag: number + ) { + super(errorStatus, errorContext); + this.name = "NativeAuthError"; + this.statusCode = errorCode; + this.tag = errorTag.toString(); + Object.setPrototypeOf(this, NativeAuthError.prototype); + } +} diff --git a/lib/msal-common/src/exports-common.ts b/lib/msal-common/src/exports-common.ts index 3c6b438995..8879a69755 100644 --- a/lib/msal-common/src/exports-common.ts +++ b/lib/msal-common/src/exports-common.ts @@ -140,6 +140,7 @@ export { AuthErrorCodes, createAuthError, } from "./error/AuthError.js"; +export { NativeAuthError } from "./error/NativeAuthError.js"; export { ServerError } from "./error/ServerError.js"; export { NetworkError, createNetworkError } from "./error/NetworkError.js"; export { From 700cc102fcb9927d2706dd01090c731d9cbb7642 Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Wed, 29 Oct 2025 21:06:48 -0700 Subject: [PATCH 02/12] Change files --- ...e-msal-common-fa718400-1f30-4ec0-a922-9ab96a7fe335.json | 7 +++++++ ...de-extensions-05784d6a-75fa-4bbf-adf4-543636d3ae42.json | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 change/@azure-msal-common-fa718400-1f30-4ec0-a922-9ab96a7fe335.json create mode 100644 change/@azure-msal-node-extensions-05784d6a-75fa-4bbf-adf4-543636d3ae42.json diff --git a/change/@azure-msal-common-fa718400-1f30-4ec0-a922-9ab96a7fe335.json b/change/@azure-msal-common-fa718400-1f30-4ec0-a922-9ab96a7fe335.json new file mode 100644 index 0000000000..35247871a9 --- /dev/null +++ b/change/@azure-msal-common-fa718400-1f30-4ec0-a922-9ab96a7fe335.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "error surfacing changes", + "packageName": "@azure/msal-common", + "email": "akaliugonna@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@azure-msal-node-extensions-05784d6a-75fa-4bbf-adf4-543636d3ae42.json b/change/@azure-msal-node-extensions-05784d6a-75fa-4bbf-adf4-543636d3ae42.json new file mode 100644 index 0000000000..d2e8780492 --- /dev/null +++ b/change/@azure-msal-node-extensions-05784d6a-75fa-4bbf-adf4-543636d3ae42.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "error surfacing changes", + "packageName": "@azure/msal-node-extensions", + "email": "akaliugonna@microsoft.com", + "dependentChangeType": "patch" +} From dd76def0bad370615ce0d72a91eca017848c2f05 Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Wed, 29 Oct 2025 22:25:44 -0700 Subject: [PATCH 03/12] api changes --- .../src/broker/NativeBrokerPlugin.ts | 3 +-- lib/msal-common/apiReview/msal-common.api.md | 10 ++++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts index b68fd5eb4f..0c98d7692f 100644 --- a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts +++ b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts @@ -709,8 +709,7 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { ); break; default: - wrappedError = nativeAuthError; - break; + return nativeAuthError; } wrappedError.msalNodeRuntimeError = nativeAuthError; diff --git a/lib/msal-common/apiReview/msal-common.api.md b/lib/msal-common/apiReview/msal-common.api.md index b41b9b944a..cdf80623a5 100644 --- a/lib/msal-common/apiReview/msal-common.api.md +++ b/lib/msal-common/apiReview/msal-common.api.md @@ -598,6 +598,7 @@ export class AuthError extends Error { correlationId: string; errorCode: string; errorMessage: string; + msalNodeRuntimeError?: NativeAuthError; // (undocumented) setCorrelationId(correlationId: string): void; subError: string; @@ -3062,6 +3063,15 @@ const NATIVE_BROKER = "nativebroker"; // @public (undocumented) const nativeAccountUnavailable = "native_account_unavailable"; +// Warning: (ae-missing-release-tag) "NativeAuthError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class NativeAuthError extends AuthError { + constructor(errorStatus: string, errorContext: string, errorCode: number, errorTag: number); + statusCode: number; + tag: string; +} + // Warning: (ae-missing-release-tag) "NativeRequest" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) From 3b53bffdc3f58c996b0ed93282bba8ca7895c0ee Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Wed, 29 Oct 2025 23:26:50 -0700 Subject: [PATCH 04/12] move nativeautherror and strilutils to msal/common --- .../src/broker/NativeBrokerPlugin.ts | 6 ++--- .../src/error/NativeAuthError.ts | 25 ------------------- extensions/msal-node-extensions/src/index.ts | 1 - .../test/broker/NativeBrokerPlugin.spec.ts | 8 +++--- lib/msal-common/src/error/NativeAuthError.ts | 3 ++- lib/msal-common/src/exports-common.ts | 1 + .../src/utils/NativeBrokerStringUtils.ts | 2 +- .../utils/NativeBrokerStringUtils.spec.ts | 12 ++++----- 8 files changed, 17 insertions(+), 41 deletions(-) delete mode 100644 extensions/msal-node-extensions/src/error/NativeAuthError.ts rename extensions/msal-node-extensions/src/utils/StringUtils.ts => lib/msal-common/src/utils/NativeBrokerStringUtils.ts (95%) rename extensions/msal-node-extensions/test/utils/StringUtils.test.ts => lib/msal-common/test/utils/NativeBrokerStringUtils.spec.ts (58%) diff --git a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts index 0c98d7692f..14beca08be 100644 --- a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts +++ b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts @@ -18,6 +18,8 @@ import { InteractionRequiredAuthError, Logger, LoggerOptions, + NativeAuthError, + NativeBrokerStringUtils, NativeRequest, NativeSignOutRequest, PromptValue, @@ -38,8 +40,6 @@ import { LogLevel as MsalRuntimeLogLevel, } from "@azure/msal-node-runtime"; import { ErrorCodes } from "../utils/Constants.js"; -import { StringUtils } from "../utils/StringUtils.js"; -import { NativeAuthError } from "../error/NativeAuthError.js"; import { version, name } from "../packageMetadata.js"; export class NativeBrokerPlugin implements INativeBrokerPlugin { @@ -656,7 +656,7 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { ) { const { errorCode, errorStatus, errorContext, errorTag } = error as MsalRuntimeError; - const tagString = StringUtils.tagToString(errorTag); + const tagString = NativeBrokerStringUtils.tagToString(errorTag); const enhancedErrorContext = errorContext ? `${errorContext} (Error Code: ${errorCode}, Tag: ${tagString})` : `(Error Code: ${errorCode}, Tag: ${tagString})`; diff --git a/extensions/msal-node-extensions/src/error/NativeAuthError.ts b/extensions/msal-node-extensions/src/error/NativeAuthError.ts deleted file mode 100644 index b5949ea259..0000000000 --- a/extensions/msal-node-extensions/src/error/NativeAuthError.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - */ - -import { AuthError } from "@azure/msal-common/node"; -import { StringUtils } from "../utils/StringUtils.js"; - -export class NativeAuthError extends AuthError { - public statusCode: number; - public tag: string; - - constructor( - errorStatus: string, - errorContext: string, - errorCode: number, - errorTag: number - ) { - super(errorStatus, errorContext); - this.name = "NativeAuthError"; - this.statusCode = errorCode; - this.tag = StringUtils.tagToString(errorTag); - Object.setPrototypeOf(this, NativeAuthError.prototype); - } -} diff --git a/extensions/msal-node-extensions/src/index.ts b/extensions/msal-node-extensions/src/index.ts index 7ffdba3e49..cccd6af36b 100644 --- a/extensions/msal-node-extensions/src/index.ts +++ b/extensions/msal-node-extensions/src/index.ts @@ -14,5 +14,4 @@ export { CrossPlatformLockOptions } from "./lock/CrossPlatformLockOptions.js"; export { PersistenceCreator } from "./persistence/PersistenceCreator.js"; export { IPersistenceConfiguration } from "./persistence/IPersistenceConfiguration.js"; export { Environment } from "./utils/Environment.js"; -export { StringUtils } from "./utils/StringUtils.js"; export { NativeBrokerPlugin } from "./broker/NativeBrokerPlugin.js"; diff --git a/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts b/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts index 3656bee021..af7f0efad0 100644 --- a/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts +++ b/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts @@ -52,10 +52,10 @@ import { ServerError, AuthenticationScheme, TimeUtils, + NativeAuthError, + NativeBrokerStringUtils, } from "@azure/msal-common"; import { randomUUID } from "crypto"; -import { NativeAuthError } from "../../src/error/NativeAuthError"; -import { StringUtils } from "../../src/utils/StringUtils.js"; import { testMsalRuntimeAccount, testAccountInfo, @@ -90,12 +90,12 @@ if (process.platform === "win32") { const enhancedErrorContext = msalRuntimeExampleError.errorContext ? `${msalRuntimeExampleError.errorContext} (Error Code: ${ msalRuntimeExampleError.errorCode - }, Tag: ${StringUtils.tagToString( + }, Tag: ${NativeBrokerStringUtils.tagToString( msalRuntimeExampleError.errorTag )})` : `(Error Code: ${ msalRuntimeExampleError.errorCode - }, Tag: ${StringUtils.tagToString( + }, Tag: ${NativeBrokerStringUtils.tagToString( msalRuntimeExampleError.errorTag )})`; const testNativeAuthError = new NativeAuthError( diff --git a/lib/msal-common/src/error/NativeAuthError.ts b/lib/msal-common/src/error/NativeAuthError.ts index 6dcb188fd7..0dcf41914d 100644 --- a/lib/msal-common/src/error/NativeAuthError.ts +++ b/lib/msal-common/src/error/NativeAuthError.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. */ +import { NativeBrokerStringUtils } from "../utils/NativeBrokerStringUtils.js"; import { AuthError } from "./AuthError.js"; /** @@ -28,7 +29,7 @@ export class NativeAuthError extends AuthError { super(errorStatus, errorContext); this.name = "NativeAuthError"; this.statusCode = errorCode; - this.tag = errorTag.toString(); + this.tag = NativeBrokerStringUtils.tagToString(errorTag); Object.setPrototypeOf(this, NativeAuthError.prototype); } } diff --git a/lib/msal-common/src/exports-common.ts b/lib/msal-common/src/exports-common.ts index 8879a69755..a5246eed9f 100644 --- a/lib/msal-common/src/exports-common.ts +++ b/lib/msal-common/src/exports-common.ts @@ -190,6 +190,7 @@ export { EncodingTypes, } from "./utils/Constants.js"; export { StringUtils } from "./utils/StringUtils.js"; +export { NativeBrokerStringUtils } from "./utils/NativeBrokerStringUtils.js"; export { StringDict } from "./utils/MsalTypes.js"; export { ProtocolUtils, diff --git a/extensions/msal-node-extensions/src/utils/StringUtils.ts b/lib/msal-common/src/utils/NativeBrokerStringUtils.ts similarity index 95% rename from extensions/msal-node-extensions/src/utils/StringUtils.ts rename to lib/msal-common/src/utils/NativeBrokerStringUtils.ts index 43b251b9ad..98c377541d 100644 --- a/extensions/msal-node-extensions/src/utils/StringUtils.ts +++ b/lib/msal-common/src/utils/NativeBrokerStringUtils.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. */ -export class StringUtils { +export class NativeBrokerStringUtils { /** * Converts a numeric tag to a string representation * @param tag - The numeric tag to convert diff --git a/extensions/msal-node-extensions/test/utils/StringUtils.test.ts b/lib/msal-common/test/utils/NativeBrokerStringUtils.spec.ts similarity index 58% rename from extensions/msal-node-extensions/test/utils/StringUtils.test.ts rename to lib/msal-common/test/utils/NativeBrokerStringUtils.spec.ts index f5d26d6add..1b5fd2d42b 100644 --- a/extensions/msal-node-extensions/test/utils/StringUtils.test.ts +++ b/lib/msal-common/test/utils/NativeBrokerStringUtils.spec.ts @@ -3,17 +3,17 @@ * Licensed under the MIT License. */ -import { StringUtils } from "../../src/utils/StringUtils.js"; +import { NativeBrokerStringUtils } from "../../src/utils/NativeBrokerStringUtils.js"; -describe("StringUtils", () => { +describe("NativeBrokerStringUtils", () => { describe("tagToString tests", () => { it("Returns 'UNTAG' for tag value 0", () => { - expect(StringUtils.tagToString(0)).toBe("UNTAG"); + expect(NativeBrokerStringUtils.tagToString(0)).toBe("UNTAG"); }); it("Converts numeric tag to 5-character string", () => { const tag = 0x01234567; - const result = StringUtils.tagToString(tag); + const result = NativeBrokerStringUtils.tagToString(tag); expect(result).toHaveLength(5); expect(typeof result).toBe("string"); @@ -21,8 +21,8 @@ describe("StringUtils", () => { it("Produce same results for same input", () => { const tag = 0x12345678; - const result1 = StringUtils.tagToString(tag); - const result2 = StringUtils.tagToString(tag); + const result1 = NativeBrokerStringUtils.tagToString(tag); + const result2 = NativeBrokerStringUtils.tagToString(tag); expect(result1).toBe(result2); }); From 1e4998eb18dd2410794c97e102f828493ad393aa Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Wed, 29 Oct 2025 23:53:26 -0700 Subject: [PATCH 05/12] api changes --- lib/msal-common/apiReview/msal-common.api.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/msal-common/apiReview/msal-common.api.md b/lib/msal-common/apiReview/msal-common.api.md index cdf80623a5..bfc06896bb 100644 --- a/lib/msal-common/apiReview/msal-common.api.md +++ b/lib/msal-common/apiReview/msal-common.api.md @@ -3072,6 +3072,13 @@ export class NativeAuthError extends AuthError { tag: string; } +// Warning: (ae-missing-release-tag) "NativeBrokerStringUtils" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class NativeBrokerStringUtils { + static tagToString(tag: number): string; +} + // Warning: (ae-missing-release-tag) "NativeRequest" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) From b8e45fca9b369b300d40c2c6437232be98e26817 Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Fri, 31 Oct 2025 12:48:36 -0700 Subject: [PATCH 06/12] create clone --- .../src/broker/NativeBrokerPlugin.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts index 14beca08be..d4c306f1e7 100644 --- a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts +++ b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts @@ -709,7 +709,16 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { ); break; default: - return nativeAuthError; + wrappedError = nativeAuthError; + // Clone error to avoid circular reference + const clonedError = new NativeAuthError( + ErrorStatus[errorStatus], + enhancedErrorContext, + errorCode, + errorTag + ); + wrappedError.msalNodeRuntimeError = clonedError; + return wrappedError; } wrappedError.msalNodeRuntimeError = nativeAuthError; From 3ab016218b06e0d96155004ecaa3681881685245 Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Wed, 5 Nov 2025 17:29:09 -0500 Subject: [PATCH 07/12] rename NativeAuthError --- .../src/broker/NativeBrokerPlugin.ts | 12 ++--- .../test/broker/NativeBrokerPlugin.spec.ts | 50 +++++++++---------- lib/msal-common/src/error/AuthError.ts | 6 +-- ...iveAuthError.ts => PlatformBrokerError.ts} | 6 +-- lib/msal-common/src/exports-common.ts | 2 +- 5 files changed, 38 insertions(+), 38 deletions(-) rename lib/msal-common/src/error/{NativeAuthError.ts => PlatformBrokerError.ts} (82%) diff --git a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts index d4c306f1e7..dec72f0d18 100644 --- a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts +++ b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts @@ -18,7 +18,7 @@ import { InteractionRequiredAuthError, Logger, LoggerOptions, - NativeAuthError, + PlatformBrokerError, NativeBrokerStringUtils, NativeRequest, NativeSignOutRequest, @@ -648,7 +648,7 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { ); } - private wrapError(error: unknown): NativeAuthError | Object | null { + private wrapError(error: unknown): PlatformBrokerError | Object | null { if ( error && typeof error === "object" && @@ -661,7 +661,7 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { ? `${errorContext} (Error Code: ${errorCode}, Tag: ${tagString})` : `(Error Code: ${errorCode}, Tag: ${tagString})`; - const nativeAuthError = new NativeAuthError( + const platformBrokerError = new PlatformBrokerError( ErrorStatus[errorStatus], enhancedErrorContext, errorCode, @@ -709,9 +709,9 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { ); break; default: - wrappedError = nativeAuthError; + wrappedError = platformBrokerError; // Clone error to avoid circular reference - const clonedError = new NativeAuthError( + const clonedError = new PlatformBrokerError( ErrorStatus[errorStatus], enhancedErrorContext, errorCode, @@ -721,7 +721,7 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { return wrappedError; } - wrappedError.msalNodeRuntimeError = nativeAuthError; + wrappedError.msalNodeRuntimeError = platformBrokerError; return wrappedError; } throw error; diff --git a/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts b/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts index af7f0efad0..45e29de210 100644 --- a/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts +++ b/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts @@ -52,7 +52,7 @@ import { ServerError, AuthenticationScheme, TimeUtils, - NativeAuthError, + PlatformBrokerError, NativeBrokerStringUtils, } from "@azure/msal-common"; import { randomUUID } from "crypto"; @@ -98,7 +98,7 @@ if (process.platform === "win32") { }, Tag: ${NativeBrokerStringUtils.tagToString( msalRuntimeExampleError.errorTag )})`; - const testNativeAuthError = new NativeAuthError( + const testPlatformBrokerError = new PlatformBrokerError( ErrorStatus[msalRuntimeExampleError.errorStatus], enhancedErrorContext, msalRuntimeExampleError.errorCode, @@ -191,8 +191,8 @@ if (process.platform === "win32") { testCorrelationId ) .catch((error) => { - expect(error).toStrictEqual( - testNativeAuthError + expect(error).toStrictEqual( + testPlatformBrokerError ); done(); }); @@ -233,8 +233,8 @@ if (process.platform === "win32") { testCorrelationId ) .catch((error) => { - expect(error).toStrictEqual( - testNativeAuthError + expect(error).toStrictEqual( + testPlatformBrokerError ); done(); }); @@ -289,8 +289,8 @@ if (process.platform === "win32") { nativeBrokerPlugin .getAllAccounts(TEST_CLIENT_ID, testCorrelationId) .catch((error) => { - expect(error).toStrictEqual( - testNativeAuthError + expect(error).toStrictEqual( + testPlatformBrokerError ); done(); }); @@ -326,8 +326,8 @@ if (process.platform === "win32") { nativeBrokerPlugin .getAllAccounts(TEST_CLIENT_ID, testCorrelationId) .catch((error) => { - expect(error).toStrictEqual( - testNativeAuthError + expect(error).toStrictEqual( + testPlatformBrokerError ); done(); }); @@ -570,8 +570,8 @@ if (process.platform === "win32") { nativeBrokerPlugin .acquireTokenSilent(request) .catch((error) => { - expect(error).toStrictEqual( - testNativeAuthError + expect(error).toStrictEqual( + testPlatformBrokerError ); done(); }); @@ -598,8 +598,8 @@ if (process.platform === "win32") { nativeBrokerPlugin .acquireTokenSilent(request) .catch((error) => { - expect(error).toStrictEqual( - testNativeAuthError + expect(error).toStrictEqual( + testPlatformBrokerError ); done(); }); @@ -649,8 +649,8 @@ if (process.platform === "win32") { nativeBrokerPlugin .acquireTokenSilent(request) .catch((error) => { - expect(error).toStrictEqual( - testNativeAuthError + expect(error).toStrictEqual( + testPlatformBrokerError ); done(); }); @@ -1233,7 +1233,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testNativeAuthError); + ).rejects.toThrowError(testPlatformBrokerError); }); it("Throws error if AcquireTokenInteractivelyAsync returns error", async () => { @@ -1303,7 +1303,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testNativeAuthError); + ).rejects.toThrowError(testPlatformBrokerError); }); it("Throws error if SignInAsync returns error", async () => { @@ -1348,7 +1348,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testNativeAuthError); + ).rejects.toThrowError(testPlatformBrokerError); }); it("Throws error if AcquireTokenSilentlyAsync returns error", async () => { @@ -1417,7 +1417,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testNativeAuthError); + ).rejects.toThrowError(testPlatformBrokerError); }); it("Throws error if SignInSilentlyAsync returns error", async () => { @@ -1464,7 +1464,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testNativeAuthError); + ).rejects.toThrowError(testPlatformBrokerError); }); it("Throws error if MsalRuntime API throws", async () => { @@ -1486,7 +1486,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testNativeAuthError); + ).rejects.toThrowError(testPlatformBrokerError); }); it("sets the correct redirectUri when calling acquireTokenInteractive", async () => { @@ -1681,7 +1681,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.signOut(request) - ).rejects.toThrowError(testNativeAuthError); + ).rejects.toThrowError(testPlatformBrokerError); }); it("Throws error if SignOutSilentlyAsync API throws", async () => { @@ -1722,7 +1722,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.signOut(request) - ).rejects.toThrowError(testNativeAuthError); + ).rejects.toThrowError(testPlatformBrokerError); }); }); @@ -2315,7 +2315,7 @@ if (process.platform === "win32") { ); expect(error.msalNodeRuntimeError).toBeDefined(); expect(error.msalNodeRuntimeError).toBeInstanceOf( - NativeAuthError + PlatformBrokerError ); done(); }); diff --git a/lib/msal-common/src/error/AuthError.ts b/lib/msal-common/src/error/AuthError.ts index f66bd39e61..4c331e9647 100644 --- a/lib/msal-common/src/error/AuthError.ts +++ b/lib/msal-common/src/error/AuthError.ts @@ -5,7 +5,7 @@ import { Constants } from "../utils/Constants.js"; import * as AuthErrorCodes from "./AuthErrorCodes.js"; -import type { NativeAuthError } from "./NativeAuthError.js"; +import type { PlatformBrokerError } from "./PlatformBrokerError.js"; export { AuthErrorCodes }; export const AuthErrorMessages = { @@ -54,9 +54,9 @@ export class AuthError extends Error { correlationId: string; /** - * Default NativeAuthError from MsalNodeRuntime when broker is enabled + * Default PlatformBrokerError from MsalNodeRuntime when broker is enabled */ - msalNodeRuntimeError?: NativeAuthError; + msalNodeRuntimeError?: PlatformBrokerError; constructor(errorCode?: string, errorMessage?: string, suberror?: string) { const errorString = errorMessage diff --git a/lib/msal-common/src/error/NativeAuthError.ts b/lib/msal-common/src/error/PlatformBrokerError.ts similarity index 82% rename from lib/msal-common/src/error/NativeAuthError.ts rename to lib/msal-common/src/error/PlatformBrokerError.ts index 0dcf41914d..b01279fc4a 100644 --- a/lib/msal-common/src/error/NativeAuthError.ts +++ b/lib/msal-common/src/error/PlatformBrokerError.ts @@ -9,7 +9,7 @@ import { AuthError } from "./AuthError.js"; /** * Error class for MSAL Runtime errors that preserves detailed broker information */ -export class NativeAuthError extends AuthError { +export class PlatformBrokerError extends AuthError { /** * Numeric error code from MSAL Runtime */ @@ -27,9 +27,9 @@ export class NativeAuthError extends AuthError { errorTag: number ) { super(errorStatus, errorContext); - this.name = "NativeAuthError"; + this.name = "PlatformBrokerError"; this.statusCode = errorCode; this.tag = NativeBrokerStringUtils.tagToString(errorTag); - Object.setPrototypeOf(this, NativeAuthError.prototype); + Object.setPrototypeOf(this, PlatformBrokerError.prototype); } } diff --git a/lib/msal-common/src/exports-common.ts b/lib/msal-common/src/exports-common.ts index a5246eed9f..16297fb789 100644 --- a/lib/msal-common/src/exports-common.ts +++ b/lib/msal-common/src/exports-common.ts @@ -140,7 +140,7 @@ export { AuthErrorCodes, createAuthError, } from "./error/AuthError.js"; -export { NativeAuthError } from "./error/NativeAuthError.js"; +export { PlatformBrokerError } from "./error/PlatformBrokerError.js"; export { ServerError } from "./error/ServerError.js"; export { NetworkError, createNetworkError } from "./error/NetworkError.js"; export { From f52b10587fb533a98d45e39b19475a396f27173b Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Wed, 5 Nov 2025 19:21:25 -0500 Subject: [PATCH 08/12] move tagtoStirng under PlatformBrokerError --- .../src/broker/NativeBrokerPlugin.ts | 19 ++++------ .../test/broker/NativeBrokerPlugin.spec.ts | 20 ++-------- lib/msal-common/apiReview/msal-common.api.md | 13 ++----- lib/msal-common/src/error/AuthError.ts | 2 +- .../src/error/PlatformBrokerError.ts | 37 +++++++++++++++++-- lib/msal-common/src/exports-common.ts | 1 - 6 files changed, 49 insertions(+), 43 deletions(-) diff --git a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts index dec72f0d18..0ce004d133 100644 --- a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts +++ b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts @@ -19,7 +19,6 @@ import { Logger, LoggerOptions, PlatformBrokerError, - NativeBrokerStringUtils, NativeRequest, NativeSignOutRequest, PromptValue, @@ -656,14 +655,10 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { ) { const { errorCode, errorStatus, errorContext, errorTag } = error as MsalRuntimeError; - const tagString = NativeBrokerStringUtils.tagToString(errorTag); - const enhancedErrorContext = errorContext - ? `${errorContext} (Error Code: ${errorCode}, Tag: ${tagString})` - : `(Error Code: ${errorCode}, Tag: ${tagString})`; - const platformBrokerError = new PlatformBrokerError( + const msalNodeRuntimeError = new PlatformBrokerError( ErrorStatus[errorStatus], - enhancedErrorContext, + errorContext, errorCode, errorTag ); @@ -675,7 +670,7 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { case ErrorStatus.AccountUnusable: wrappedError = new InteractionRequiredAuthError( ErrorCodes.INTERATION_REQUIRED_ERROR_CODE, - enhancedErrorContext + msalNodeRuntimeError.message ); break; case ErrorStatus.NoNetwork: @@ -709,19 +704,19 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { ); break; default: - wrappedError = platformBrokerError; + wrappedError = msalNodeRuntimeError; // Clone error to avoid circular reference const clonedError = new PlatformBrokerError( ErrorStatus[errorStatus], - enhancedErrorContext, + errorContext, errorCode, errorTag ); - wrappedError.msalNodeRuntimeError = clonedError; + wrappedError.platformBrokerError = clonedError; return wrappedError; } - wrappedError.msalNodeRuntimeError = platformBrokerError; + wrappedError.platformBrokerError = msalNodeRuntimeError; return wrappedError; } throw error; diff --git a/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts b/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts index 45e29de210..fa4630343a 100644 --- a/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts +++ b/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts @@ -53,7 +53,6 @@ import { AuthenticationScheme, TimeUtils, PlatformBrokerError, - NativeBrokerStringUtils, } from "@azure/msal-common"; import { randomUUID } from "crypto"; import { @@ -87,20 +86,9 @@ function createMockAuthResult( if (process.platform === "win32") { describe("NativeBrokerPlugin", () => { - const enhancedErrorContext = msalRuntimeExampleError.errorContext - ? `${msalRuntimeExampleError.errorContext} (Error Code: ${ - msalRuntimeExampleError.errorCode - }, Tag: ${NativeBrokerStringUtils.tagToString( - msalRuntimeExampleError.errorTag - )})` - : `(Error Code: ${ - msalRuntimeExampleError.errorCode - }, Tag: ${NativeBrokerStringUtils.tagToString( - msalRuntimeExampleError.errorTag - )})`; const testPlatformBrokerError = new PlatformBrokerError( ErrorStatus[msalRuntimeExampleError.errorStatus], - enhancedErrorContext, + msalRuntimeExampleError.errorContext, msalRuntimeExampleError.errorCode, msalRuntimeExampleError.errorTag ); @@ -2258,7 +2246,7 @@ if (process.platform === "win32") { }); }); - it("Attaches msalNodeRuntimeError with runtime details to wrapped MSAL.js errors", (done) => { + it("Attaches platformBrokerError with runtime details to wrapped MSAL.js errors", (done) => { const testCorrelationId = generateCorrelationId(); jest.spyOn( @@ -2313,8 +2301,8 @@ if (process.platform === "win32") { expect(error).toBeInstanceOf( InteractionRequiredAuthError ); - expect(error.msalNodeRuntimeError).toBeDefined(); - expect(error.msalNodeRuntimeError).toBeInstanceOf( + expect(error.platformBrokerError).toBeDefined(); + expect(error.platformBrokerError).toBeInstanceOf( PlatformBrokerError ); done(); diff --git a/lib/msal-common/apiReview/msal-common.api.md b/lib/msal-common/apiReview/msal-common.api.md index 51fd1d4090..5ad70b35d1 100644 --- a/lib/msal-common/apiReview/msal-common.api.md +++ b/lib/msal-common/apiReview/msal-common.api.md @@ -598,7 +598,7 @@ export class AuthError extends Error { correlationId: string; errorCode: string; errorMessage: string; - msalNodeRuntimeError?: NativeAuthError; + platformBrokerError?: PlatformBrokerError; // (undocumented) setCorrelationId(correlationId: string): void; subError: string; @@ -3063,22 +3063,15 @@ const NATIVE_BROKER = "nativebroker"; // @public (undocumented) const nativeAccountUnavailable = "native_account_unavailable"; -// Warning: (ae-missing-release-tag) "NativeAuthError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "PlatformBrokerError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export class NativeAuthError extends AuthError { +export class PlatformBrokerError extends AuthError { constructor(errorStatus: string, errorContext: string, errorCode: number, errorTag: number); statusCode: number; tag: string; } -// Warning: (ae-missing-release-tag) "NativeBrokerStringUtils" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export class NativeBrokerStringUtils { - static tagToString(tag: number): string; -} - // Warning: (ae-missing-release-tag) "NativeRequest" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/lib/msal-common/src/error/AuthError.ts b/lib/msal-common/src/error/AuthError.ts index 4c331e9647..1d8679dcf3 100644 --- a/lib/msal-common/src/error/AuthError.ts +++ b/lib/msal-common/src/error/AuthError.ts @@ -56,7 +56,7 @@ export class AuthError extends Error { /** * Default PlatformBrokerError from MsalNodeRuntime when broker is enabled */ - msalNodeRuntimeError?: PlatformBrokerError; + platformBrokerError?: PlatformBrokerError; constructor(errorCode?: string, errorMessage?: string, suberror?: string) { const errorString = errorMessage diff --git a/lib/msal-common/src/error/PlatformBrokerError.ts b/lib/msal-common/src/error/PlatformBrokerError.ts index b01279fc4a..ce3c0d7e6e 100644 --- a/lib/msal-common/src/error/PlatformBrokerError.ts +++ b/lib/msal-common/src/error/PlatformBrokerError.ts @@ -3,9 +3,35 @@ * Licensed under the MIT License. */ -import { NativeBrokerStringUtils } from "../utils/NativeBrokerStringUtils.js"; import { AuthError } from "./AuthError.js"; +/** + * Converts a numeric tag to a string representation + * @param tag - The numeric tag to convert + * @returns The string representation of the tag + */ +function tagToString(tag: number): string { + if (tag === 0) { + return "UNTAG"; + } + + const tagSymbolSpace = + "abcdefghijklmnopqrstuvwxyz0123456789****************************"; + let tagBuffer = "*****"; + + const chars = [ + tagSymbolSpace[(tag >> 24) & 0x3f], + tagSymbolSpace[(tag >> 18) & 0x3f], + tagSymbolSpace[(tag >> 12) & 0x3f], + tagSymbolSpace[(tag >> 6) & 0x3f], + tagSymbolSpace[(tag >> 0) & 0x3f], + ]; + + tagBuffer = chars.join(""); + + return tagBuffer; +} + /** * Error class for MSAL Runtime errors that preserves detailed broker information */ @@ -26,10 +52,15 @@ export class PlatformBrokerError extends AuthError { errorCode: number, errorTag: number ) { - super(errorStatus, errorContext); + const tagString = tagToString(errorTag); + const enhancedErrorContext = errorContext + ? `${errorContext} (Error Code: ${errorCode}, Tag: ${tagString})` + : `(Error Code: ${errorCode}, Tag: ${tagString})`; + + super(errorStatus, enhancedErrorContext); this.name = "PlatformBrokerError"; this.statusCode = errorCode; - this.tag = NativeBrokerStringUtils.tagToString(errorTag); + this.tag = tagString; Object.setPrototypeOf(this, PlatformBrokerError.prototype); } } diff --git a/lib/msal-common/src/exports-common.ts b/lib/msal-common/src/exports-common.ts index 16297fb789..67ece7ff2f 100644 --- a/lib/msal-common/src/exports-common.ts +++ b/lib/msal-common/src/exports-common.ts @@ -190,7 +190,6 @@ export { EncodingTypes, } from "./utils/Constants.js"; export { StringUtils } from "./utils/StringUtils.js"; -export { NativeBrokerStringUtils } from "./utils/NativeBrokerStringUtils.js"; export { StringDict } from "./utils/MsalTypes.js"; export { ProtocolUtils, From f679480f46d3314f2b5e0f3a928b6c42de20665e Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Wed, 5 Nov 2025 19:53:50 -0500 Subject: [PATCH 09/12] api changes --- lib/msal-common/apiReview/msal-common.api.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/msal-common/apiReview/msal-common.api.md b/lib/msal-common/apiReview/msal-common.api.md index 5ad70b35d1..c44db69ce3 100644 --- a/lib/msal-common/apiReview/msal-common.api.md +++ b/lib/msal-common/apiReview/msal-common.api.md @@ -3063,15 +3063,6 @@ const NATIVE_BROKER = "nativebroker"; // @public (undocumented) const nativeAccountUnavailable = "native_account_unavailable"; -// Warning: (ae-missing-release-tag) "PlatformBrokerError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public -export class PlatformBrokerError extends AuthError { - constructor(errorStatus: string, errorContext: string, errorCode: number, errorTag: number); - statusCode: number; - tag: string; -} - // Warning: (ae-missing-release-tag) "NativeRequest" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -3672,6 +3663,15 @@ export type PkceCodes = { // @public (undocumented) const pkceParamsMissing = "pkce_params_missing"; +// Warning: (ae-missing-release-tag) "PlatformBrokerError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class PlatformBrokerError extends AuthError { + constructor(errorStatus: string, errorContext: string, errorCode: number, errorTag: number); + statusCode: number; + tag: string; +} + // Warning: (ae-internal-missing-underscore) The name "PopTokenGenerator" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented) From 38f4a2e21005f80cacbacc6383d4ce97b6b01f21 Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Fri, 7 Nov 2025 12:16:32 -0500 Subject: [PATCH 10/12] fix format --- lib/msal-common/src/error/PlatformBrokerError.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msal-common/src/error/PlatformBrokerError.ts b/lib/msal-common/src/error/PlatformBrokerError.ts index ce3c0d7e6e..6085fd9498 100644 --- a/lib/msal-common/src/error/PlatformBrokerError.ts +++ b/lib/msal-common/src/error/PlatformBrokerError.ts @@ -56,7 +56,7 @@ export class PlatformBrokerError extends AuthError { const enhancedErrorContext = errorContext ? `${errorContext} (Error Code: ${errorCode}, Tag: ${tagString})` : `(Error Code: ${errorCode}, Tag: ${tagString})`; - + super(errorStatus, enhancedErrorContext); this.name = "PlatformBrokerError"; this.statusCode = errorCode; From 827ac7eb378e049494b2c51ad21a513d0d81e0dd Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Tue, 11 Nov 2025 14:44:07 -0800 Subject: [PATCH 11/12] address comments --- .../src/broker/NativeBrokerPlugin.ts | 11 +-- .../test/broker/NativeBrokerPlugin.spec.ts | 84 ++++++++++++++----- lib/msal-common/src/error/ClientAuthError.ts | 6 ++ .../src/error/ClientAuthErrorCodes.ts | 1 + .../src/utils/NativeBrokerStringUtils.ts | 33 -------- .../utils/NativeBrokerStringUtils.spec.ts | 30 ------- 6 files changed, 71 insertions(+), 94 deletions(-) delete mode 100644 lib/msal-common/src/utils/NativeBrokerStringUtils.ts delete mode 100644 lib/msal-common/test/utils/NativeBrokerStringUtils.spec.ts diff --git a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts index 0ce004d133..6b738e2abf 100644 --- a/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts +++ b/extensions/msal-node-extensions/src/broker/NativeBrokerPlugin.ts @@ -704,16 +704,9 @@ export class NativeBrokerPlugin implements INativeBrokerPlugin { ); break; default: - wrappedError = msalNodeRuntimeError; - // Clone error to avoid circular reference - const clonedError = new PlatformBrokerError( - ErrorStatus[errorStatus], - errorContext, - errorCode, - errorTag + wrappedError = createClientAuthError( + ClientAuthErrorCodes.platformBrokerError ); - wrappedError.platformBrokerError = clonedError; - return wrappedError; } wrappedError.platformBrokerError = msalNodeRuntimeError; diff --git a/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts b/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts index fa4630343a..887048178b 100644 --- a/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts +++ b/extensions/msal-node-extensions/test/broker/NativeBrokerPlugin.spec.ts @@ -53,6 +53,7 @@ import { AuthenticationScheme, TimeUtils, PlatformBrokerError, + ClientAuthError, } from "@azure/msal-common"; import { randomUUID } from "crypto"; import { @@ -93,6 +94,12 @@ if (process.platform === "win32") { msalRuntimeExampleError.errorTag ); + // Expected wrapped error for the default case (Unexpected status) + const testWrappedBrokerError = createClientAuthError( + ClientAuthErrorCodes.platformBrokerError + ); + testWrappedBrokerError.platformBrokerError = testPlatformBrokerError; + const generateCorrelationId = () => { return randomUUID(); }; @@ -179,8 +186,13 @@ if (process.platform === "win32") { testCorrelationId ) .catch((error) => { - expect(error).toStrictEqual( - testPlatformBrokerError + expect(error).toBeInstanceOf(ClientAuthError); + expect(error.errorCode).toBe( + ClientAuthErrorCodes.platformBrokerError + ); + expect(error.platformBrokerError).toBeDefined(); + expect(error.platformBrokerError).toBeInstanceOf( + PlatformBrokerError ); done(); }); @@ -221,8 +233,13 @@ if (process.platform === "win32") { testCorrelationId ) .catch((error) => { - expect(error).toStrictEqual( - testPlatformBrokerError + expect(error).toBeInstanceOf(ClientAuthError); + expect(error.errorCode).toBe( + ClientAuthErrorCodes.platformBrokerError + ); + expect(error.platformBrokerError).toBeDefined(); + expect(error.platformBrokerError).toBeInstanceOf( + PlatformBrokerError ); done(); }); @@ -277,8 +294,13 @@ if (process.platform === "win32") { nativeBrokerPlugin .getAllAccounts(TEST_CLIENT_ID, testCorrelationId) .catch((error) => { - expect(error).toStrictEqual( - testPlatformBrokerError + expect(error).toBeInstanceOf(ClientAuthError); + expect(error.errorCode).toBe( + ClientAuthErrorCodes.platformBrokerError + ); + expect(error.platformBrokerError).toBeDefined(); + expect(error.platformBrokerError).toBeInstanceOf( + PlatformBrokerError ); done(); }); @@ -314,8 +336,13 @@ if (process.platform === "win32") { nativeBrokerPlugin .getAllAccounts(TEST_CLIENT_ID, testCorrelationId) .catch((error) => { - expect(error).toStrictEqual( - testPlatformBrokerError + expect(error).toBeInstanceOf(ClientAuthError); + expect(error.errorCode).toBe( + ClientAuthErrorCodes.platformBrokerError + ); + expect(error.platformBrokerError).toBeDefined(); + expect(error.platformBrokerError).toBeInstanceOf( + PlatformBrokerError ); done(); }); @@ -558,8 +585,13 @@ if (process.platform === "win32") { nativeBrokerPlugin .acquireTokenSilent(request) .catch((error) => { - expect(error).toStrictEqual( - testPlatformBrokerError + expect(error).toBeInstanceOf(ClientAuthError); + expect(error.errorCode).toBe( + ClientAuthErrorCodes.platformBrokerError + ); + expect(error.platformBrokerError).toBeDefined(); + expect(error.platformBrokerError).toBeInstanceOf( + PlatformBrokerError ); done(); }); @@ -586,8 +618,13 @@ if (process.platform === "win32") { nativeBrokerPlugin .acquireTokenSilent(request) .catch((error) => { - expect(error).toStrictEqual( - testPlatformBrokerError + expect(error).toBeInstanceOf(ClientAuthError); + expect(error.errorCode).toBe( + ClientAuthErrorCodes.platformBrokerError + ); + expect(error.platformBrokerError).toBeDefined(); + expect(error.platformBrokerError).toBeInstanceOf( + PlatformBrokerError ); done(); }); @@ -636,8 +673,11 @@ if (process.platform === "win32") { }; nativeBrokerPlugin .acquireTokenSilent(request) - .catch((error) => { - expect(error).toStrictEqual( + .catch((error: ClientAuthError) => { + expect(error.errorCode).toBe( + ClientAuthErrorCodes.platformBrokerError + ); + expect(error.platformBrokerError).toStrictEqual( testPlatformBrokerError ); done(); @@ -1221,7 +1261,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testPlatformBrokerError); + ).rejects.toThrow(testWrappedBrokerError); }); it("Throws error if AcquireTokenInteractivelyAsync returns error", async () => { @@ -1291,7 +1331,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testPlatformBrokerError); + ).rejects.toThrow(testWrappedBrokerError); }); it("Throws error if SignInAsync returns error", async () => { @@ -1336,7 +1376,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testPlatformBrokerError); + ).rejects.toThrow(testWrappedBrokerError); }); it("Throws error if AcquireTokenSilentlyAsync returns error", async () => { @@ -1405,7 +1445,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testPlatformBrokerError); + ).rejects.toThrow(testWrappedBrokerError); }); it("Throws error if SignInSilentlyAsync returns error", async () => { @@ -1452,7 +1492,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testPlatformBrokerError); + ).rejects.toThrow(testWrappedBrokerError); }); it("Throws error if MsalRuntime API throws", async () => { @@ -1474,7 +1514,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.acquireTokenInteractive(request) - ).rejects.toThrowError(testPlatformBrokerError); + ).rejects.toThrow(testWrappedBrokerError); }); it("sets the correct redirectUri when calling acquireTokenInteractive", async () => { @@ -1669,7 +1709,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.signOut(request) - ).rejects.toThrowError(testPlatformBrokerError); + ).rejects.toThrow(testWrappedBrokerError); }); it("Throws error if SignOutSilentlyAsync API throws", async () => { @@ -1710,7 +1750,7 @@ if (process.platform === "win32") { }; await expect( nativeBrokerPlugin.signOut(request) - ).rejects.toThrowError(testPlatformBrokerError); + ).rejects.toThrow(testWrappedBrokerError); }); }); diff --git a/lib/msal-common/src/error/ClientAuthError.ts b/lib/msal-common/src/error/ClientAuthError.ts index e904bd68c0..eb3aa9b709 100644 --- a/lib/msal-common/src/error/ClientAuthError.ts +++ b/lib/msal-common/src/error/ClientAuthError.ts @@ -91,6 +91,8 @@ export const ClientAuthErrorMessages = { "This method has not been implemented", [ClientAuthErrorCodes.nestedAppAuthBridgeDisabled]: "The nested app auth bridge is disabled", + [ClientAuthErrorCodes.platformBrokerError]: + "An error occurred in the native broker. See the platformBrokerError property for details.", }; /** @@ -314,6 +316,10 @@ export const ClientAuthErrorMessage = { ClientAuthErrorCodes.nestedAppAuthBridgeDisabled ], }, + platformBrokerError: { + code: ClientAuthErrorCodes.platformBrokerError, + desc: ClientAuthErrorMessages[ClientAuthErrorCodes.platformBrokerError], + }, }; /** diff --git a/lib/msal-common/src/error/ClientAuthErrorCodes.ts b/lib/msal-common/src/error/ClientAuthErrorCodes.ts index 0e81eadfdb..688098c14e 100644 --- a/lib/msal-common/src/error/ClientAuthErrorCodes.ts +++ b/lib/msal-common/src/error/ClientAuthErrorCodes.ts @@ -50,3 +50,4 @@ export const userCanceled = "user_canceled"; export const missingTenantIdError = "missing_tenant_id_error"; export const methodNotImplemented = "method_not_implemented"; export const nestedAppAuthBridgeDisabled = "nested_app_auth_bridge_disabled"; +export const platformBrokerError = "platform_broker_error"; diff --git a/lib/msal-common/src/utils/NativeBrokerStringUtils.ts b/lib/msal-common/src/utils/NativeBrokerStringUtils.ts deleted file mode 100644 index 98c377541d..0000000000 --- a/lib/msal-common/src/utils/NativeBrokerStringUtils.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - */ - -export class NativeBrokerStringUtils { - /** - * Converts a numeric tag to a string representation - * @param tag - The numeric tag to convert - * @returns The string representation of the tag - */ - static tagToString(tag: number): string { - if (tag === 0) { - return "UNTAG"; - } - - const tagSymbolSpace = - "abcdefghijklmnopqrstuvwxyz0123456789****************************"; - let tagBuffer = "*****"; - - const chars = [ - tagSymbolSpace[(tag >> 24) & 0x3f], - tagSymbolSpace[(tag >> 18) & 0x3f], - tagSymbolSpace[(tag >> 12) & 0x3f], - tagSymbolSpace[(tag >> 6) & 0x3f], - tagSymbolSpace[(tag >> 0) & 0x3f], - ]; - - tagBuffer = chars.join(""); - - return tagBuffer; - } -} diff --git a/lib/msal-common/test/utils/NativeBrokerStringUtils.spec.ts b/lib/msal-common/test/utils/NativeBrokerStringUtils.spec.ts deleted file mode 100644 index 1b5fd2d42b..0000000000 --- a/lib/msal-common/test/utils/NativeBrokerStringUtils.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - */ - -import { NativeBrokerStringUtils } from "../../src/utils/NativeBrokerStringUtils.js"; - -describe("NativeBrokerStringUtils", () => { - describe("tagToString tests", () => { - it("Returns 'UNTAG' for tag value 0", () => { - expect(NativeBrokerStringUtils.tagToString(0)).toBe("UNTAG"); - }); - - it("Converts numeric tag to 5-character string", () => { - const tag = 0x01234567; - const result = NativeBrokerStringUtils.tagToString(tag); - - expect(result).toHaveLength(5); - expect(typeof result).toBe("string"); - }); - - it("Produce same results for same input", () => { - const tag = 0x12345678; - const result1 = NativeBrokerStringUtils.tagToString(tag); - const result2 = NativeBrokerStringUtils.tagToString(tag); - - expect(result1).toBe(result2); - }); - }); -}); From 2d93ac4ec6cb2fefe7eb19d436f1c20a5fccc3cb Mon Sep 17 00:00:00 2001 From: Ugonna Akali Date: Tue, 11 Nov 2025 15:33:23 -0800 Subject: [PATCH 12/12] api doc changes --- lib/msal-common/apiReview/msal-common.api.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/msal-common/apiReview/msal-common.api.md b/lib/msal-common/apiReview/msal-common.api.md index c44db69ce3..a4f3a7156f 100644 --- a/lib/msal-common/apiReview/msal-common.api.md +++ b/lib/msal-common/apiReview/msal-common.api.md @@ -1449,7 +1449,8 @@ declare namespace ClientAuthErrorCodes { userCanceled, missingTenantIdError, methodNotImplemented, - nestedAppAuthBridgeDisabled + nestedAppAuthBridgeDisabled, + platformBrokerError } } export { ClientAuthErrorCodes } @@ -1630,6 +1631,10 @@ export const ClientAuthErrorMessage: { code: string; desc: string; }; + platformBrokerError: { + code: string; + desc: string; + }; }; // Warning: (ae-internal-missing-underscore) The name "ClientConfiguration" should be prefixed with an underscore because the declaration is marked as @internal @@ -3672,6 +3677,11 @@ export class PlatformBrokerError extends AuthError { tag: string; } +// Warning: (ae-missing-release-tag) "platformBrokerError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +const platformBrokerError = "platform_broker_error"; + // Warning: (ae-internal-missing-underscore) The name "PopTokenGenerator" should be prefixed with an underscore because the declaration is marked as @internal // // @internal (undocumented)