From 1b9f4fb760b442d82ccf78f271ea0928b14ada66 Mon Sep 17 00:00:00 2001 From: Konstantin Shabelko Date: Fri, 10 Oct 2025 16:29:30 -0400 Subject: [PATCH 1/5] Add PCAFactory and correlation id optional params to createNestablePublicClientApplication --- .../src/app/PublicClientApplication.ts | 14 +- ...ateNestablePublicClientApplication.spec.ts | 264 ++++++++++++++++++ 2 files changed, 273 insertions(+), 5 deletions(-) create mode 100644 lib/msal-browser/test/app/createNestablePublicClientApplication.spec.ts diff --git a/lib/msal-browser/src/app/PublicClientApplication.ts b/lib/msal-browser/src/app/PublicClientApplication.ts index 3da723eaf3..3380dd31b7 100644 --- a/lib/msal-browser/src/app/PublicClientApplication.ts +++ b/lib/msal-browser/src/app/PublicClientApplication.ts @@ -373,23 +373,27 @@ export class PublicClientApplication implements IPublicClientApplication { * falls back to StandardController if NestedAppAuthController is not available * * @param configuration + * @param correlationId + * @param pcaFactory * @returns IPublicClientApplication * */ export async function createNestablePublicClientApplication( - configuration: Configuration + configuration: Configuration, + correlationId?: string, + pcaFactory?: (configuration: Configuration, controller: IController) => IPublicClientApplication, ): Promise { - const correlationId = createNewGuid(); + const cid = correlationId || createNewGuid(); const nestedAppAuth = new NestedAppOperatingContext(configuration); - await nestedAppAuth.initialize(correlationId); + await nestedAppAuth.initialize(cid); if (nestedAppAuth.isAvailable()) { const controller = new NestedAppAuthController(nestedAppAuth); - const nestablePCA = new PublicClientApplication( + const nestablePCA = pcaFactory ? pcaFactory(configuration, controller) : new PublicClientApplication( configuration, controller ); - await nestablePCA.initialize({ correlationId }); + await nestablePCA.initialize({ correlationId: cid }); return nestablePCA; } diff --git a/lib/msal-browser/test/app/createNestablePublicClientApplication.spec.ts b/lib/msal-browser/test/app/createNestablePublicClientApplication.spec.ts new file mode 100644 index 0000000000..39bf9f2447 --- /dev/null +++ b/lib/msal-browser/test/app/createNestablePublicClientApplication.spec.ts @@ -0,0 +1,264 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { + PublicClientApplication, + createNestablePublicClientApplication, + createStandardPublicClientApplication, +} from "../../src/app/PublicClientApplication.js"; +import { + TEST_CONFIG, + RANDOM_TEST_GUID, +} from "../utils/StringConstants.js"; +import { NestedAppOperatingContext } from "../../src/operatingcontext/NestedAppOperatingContext.js"; +import { NestedAppAuthController } from "../../src/controllers/NestedAppAuthController.js"; +import { Configuration, IPublicClientApplication } from "../../src/index.js"; +import { IController } from "../../src/controllers/IController.js"; +import * as BrowserCrypto from "../../src/crypto/BrowserCrypto.js"; + +// Mock modules +jest.mock("../../src/operatingcontext/NestedAppOperatingContext.js"); +jest.mock("../../src/controllers/NestedAppAuthController.js"); + +// Mock createStandardPublicClientApplication function +jest.mock("../../src/app/PublicClientApplication.js", () => ({ + ...jest.requireActual("../../src/app/PublicClientApplication.js"), + createStandardPublicClientApplication: jest.fn(), +})); + +describe("createNestablePublicClientApplication tests", () => { + let mockNestedAppOperatingContext: jest.Mocked; + let mockNestedAppAuthController: jest.Mocked; + let testConfig: Configuration; + let createNewGuidSpy: jest.SpyInstance; + let createStandardSpy: jest.SpyInstance; + + beforeEach(() => { + testConfig = { + auth: { + clientId: TEST_CONFIG.MSAL_CLIENT_ID, + authority: TEST_CONFIG.validAuthority, + }, + }; + + // Create fresh mock instances for each test + mockNestedAppOperatingContext = { + initialize: jest.fn().mockResolvedValue(true), + isAvailable: jest.fn(), + } as any; + + mockNestedAppAuthController = {} as any; + + // Mock constructors + (NestedAppOperatingContext as jest.MockedClass).mockImplementation(() => mockNestedAppOperatingContext); + (NestedAppAuthController as jest.MockedClass).mockImplementation(() => mockNestedAppAuthController); + + // Mock PublicClientApplication + jest.spyOn(PublicClientApplication.prototype, "initialize").mockResolvedValue(undefined); + + // Mock createNewGuid + createNewGuidSpy = jest.spyOn(BrowserCrypto, "createNewGuid").mockReturnValue(RANDOM_TEST_GUID); + + // Get the mocked function + createStandardSpy = createStandardPublicClientApplication as jest.MockedFunction; + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + describe("When nestedAppAuth.isAvailable() returns true", () => { + beforeEach(() => { + mockNestedAppOperatingContext.isAvailable.mockReturnValue(true); + }); + + describe("Without pcaFactory parameter", () => { + it("should create a nestable PCA using default PublicClientApplication constructor", async () => { + const result = await createNestablePublicClientApplication(testConfig); + + // Verify NestedAppOperatingContext was created with config + expect(NestedAppOperatingContext).toHaveBeenCalledWith(testConfig); + + // Verify initialize was called with generated correlation ID + expect(mockNestedAppOperatingContext.initialize).toHaveBeenCalledWith(RANDOM_TEST_GUID); + + // Verify isAvailable was called + expect(mockNestedAppOperatingContext.isAvailable).toHaveBeenCalled(); + + // Verify NestedAppAuthController was created with the operating context + expect(NestedAppAuthController).toHaveBeenCalledWith(mockNestedAppOperatingContext); + + // Verify the result is a PublicClientApplication instance + expect(result).toBeInstanceOf(PublicClientApplication); + + // Verify initialize was called on the PCA instance + expect(result.initialize).toHaveBeenCalledWith({ correlationId: RANDOM_TEST_GUID }); + }); + + it("should use provided correlation ID when specified", async () => { + // Create a fresh spy for this test to avoid interference + const freshGuidSpy = jest.spyOn(BrowserCrypto, "createNewGuid"); + const customCorrelationId = "custom-correlation-id"; + + const result = await createNestablePublicClientApplication(testConfig, customCorrelationId); + + // Verify initialize was called with custom correlation ID + expect(mockNestedAppOperatingContext.initialize).toHaveBeenCalledWith(customCorrelationId); + + // Verify initialize was called on PCA with custom correlation ID + expect(result.initialize).toHaveBeenCalledWith({ correlationId: customCorrelationId }); + + // Verify createNewGuid was not called since correlation ID was provided + expect(freshGuidSpy).not.toHaveBeenCalled(); + + freshGuidSpy.mockRestore(); + }); + + it("should generate correlation ID when not provided", async () => { + await createNestablePublicClientApplication(testConfig); + + // Verify createNewGuid was called + expect(createNewGuidSpy).toHaveBeenCalled(); + + // Verify initialize was called with generated ID + expect(mockNestedAppOperatingContext.initialize).toHaveBeenCalledWith(RANDOM_TEST_GUID); + }); + }); + + describe("With pcaFactory parameter", () => { + it("should use pcaFactory to create the PCA when provided", async () => { + const mockPCA = { + initialize: jest.fn().mockResolvedValue(undefined), + } as any; + + const mockPcaFactory = jest.fn().mockReturnValue(mockPCA); + + const result = await createNestablePublicClientApplication( + testConfig, + undefined, + mockPcaFactory + ); + + // Verify pcaFactory was called with config and controller + expect(mockPcaFactory).toHaveBeenCalledWith(testConfig, mockNestedAppAuthController); + + // Verify the returned PCA is the one from factory + expect(result).toBe(mockPCA); + + // Verify initialize was called on the factory-created PCA + expect(mockPCA.initialize).toHaveBeenCalledWith({ correlationId: RANDOM_TEST_GUID }); + }); + + it("should use pcaFactory with custom correlation ID", async () => { + // Create a fresh spy for this test to avoid interference + const freshGuidSpy = jest.spyOn(BrowserCrypto, "createNewGuid"); + const customCorrelationId = "factory-correlation-id"; + const mockPCA = { + initialize: jest.fn().mockResolvedValue(undefined), + } as any; + + const mockPcaFactory = jest.fn().mockReturnValue(mockPCA); + + const result = await createNestablePublicClientApplication( + testConfig, + customCorrelationId, + mockPcaFactory + ); + + // Verify pcaFactory was called with config and controller + expect(mockPcaFactory).toHaveBeenCalledWith(testConfig, mockNestedAppAuthController); + + // Verify initialize was called with custom correlation ID + expect(mockPCA.initialize).toHaveBeenCalledWith({ correlationId: customCorrelationId }); + + // Verify createNewGuid was not called + expect(freshGuidSpy).not.toHaveBeenCalled(); + + freshGuidSpy.mockRestore(); + }); + + it("should handle pcaFactory returning different PCA implementation", async () => { + class CustomPCA implements IPublicClientApplication { + constructor(public config: Configuration, public controller: IController) {} + initialize = jest.fn().mockResolvedValue(undefined); + // Add other required methods with minimal implementations + acquireTokenPopup = jest.fn(); + acquireTokenRedirect = jest.fn(); + acquireTokenSilent = jest.fn(); + acquireTokenByCode = jest.fn(); + addEventCallback = jest.fn(); + removeEventCallback = jest.fn(); + addPerformanceCallback = jest.fn(); + removePerformanceCallback = jest.fn(); + getAccount = jest.fn(); + getAllAccounts = jest.fn(); + handleRedirectPromise = jest.fn(); + loginPopup = jest.fn(); + loginRedirect = jest.fn(); + logoutRedirect = jest.fn(); + logoutPopup = jest.fn(); + ssoSilent = jest.fn(); + getLogger = jest.fn(); + setLogger = jest.fn(); + setActiveAccount = jest.fn(); + getActiveAccount = jest.fn(); + initializeWrapperLibrary = jest.fn(); + setNavigationClient = jest.fn(); + getConfiguration = jest.fn(); + hydrateCache = jest.fn(); + clearCache = jest.fn(); + } + + const mockPcaFactory = jest.fn().mockImplementation((config, controller) => { + return new CustomPCA(config, controller); + }); + + const result = await createNestablePublicClientApplication( + testConfig, + undefined, + mockPcaFactory + ); + + // Verify result is instance of CustomPCA + expect(result).toBeInstanceOf(CustomPCA); + expect(result.initialize).toHaveBeenCalledWith({ correlationId: RANDOM_TEST_GUID }); + }); + }); + }); + + describe("When nestedAppAuth.isAvailable() returns false", () => { + beforeEach(() => { + mockNestedAppOperatingContext.isAvailable.mockReturnValue(false); + }); + + it("should call createStandardPublicClientApplication as fallback", async () => { + const mockStandardPCA = { type: "standard" } as any; + createStandardSpy.mockResolvedValue(mockStandardPCA); + + const result = await createNestablePublicClientApplication(testConfig); + + // Should have initialized NestedAppOperatingContext first + expect(mockNestedAppOperatingContext.initialize).toHaveBeenCalledWith(RANDOM_TEST_GUID); + expect(mockNestedAppOperatingContext.isAvailable).toHaveBeenCalled(); + + // Should return a result (whether mocked or real) + expect(result).toBeDefined(); + }); + + it("should ignore pcaFactory parameter when falling back", async () => { + const mockPcaFactory = jest.fn(); + + const result = await createNestablePublicClientApplication( + testConfig, + undefined, + mockPcaFactory + ); + + // The factory should not be called since we're falling back + expect(mockPcaFactory).not.toHaveBeenCalled(); + expect(result).toBeDefined(); + }); + }); +}); From 5f5fbfd1649b2eb87769134d128030bd5ea3d967 Mon Sep 17 00:00:00 2001 From: Konstantin Shabelko Date: Fri, 10 Oct 2025 16:33:29 -0400 Subject: [PATCH 2/5] Add PCAFactory and correlation id optional params to createNestablePublicClientApplication --- .../apiReview/msal-browser.api.md | 4 +- .../src/app/PublicClientApplication.ts | 12 +- ...ateNestablePublicClientApplication.spec.ts | 119 +++++++++++++----- 3 files changed, 98 insertions(+), 37 deletions(-) diff --git a/lib/msal-browser/apiReview/msal-browser.api.md b/lib/msal-browser/apiReview/msal-browser.api.md index 885b6c051d..954bb26bf5 100644 --- a/lib/msal-browser/apiReview/msal-browser.api.md +++ b/lib/msal-browser/apiReview/msal-browser.api.md @@ -489,11 +489,13 @@ export type Configuration = { // @public function createGuid(): string; +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (ae-missing-release-tag) "createNestablePublicClientApplication" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export function createNestablePublicClientApplication(configuration: Configuration): Promise; +export function createNestablePublicClientApplication(configuration: Configuration, correlationId?: string, pcaFactory?: (configuration: Configuration, controller: IController) => IPublicClientApplication): Promise; // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (ae-missing-release-tag) "createStandardPublicClientApplication" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/lib/msal-browser/src/app/PublicClientApplication.ts b/lib/msal-browser/src/app/PublicClientApplication.ts index 3380dd31b7..975853f652 100644 --- a/lib/msal-browser/src/app/PublicClientApplication.ts +++ b/lib/msal-browser/src/app/PublicClientApplication.ts @@ -381,7 +381,10 @@ export class PublicClientApplication implements IPublicClientApplication { export async function createNestablePublicClientApplication( configuration: Configuration, correlationId?: string, - pcaFactory?: (configuration: Configuration, controller: IController) => IPublicClientApplication, + pcaFactory?: ( + configuration: Configuration, + controller: IController + ) => IPublicClientApplication ): Promise { const cid = correlationId || createNewGuid(); const nestedAppAuth = new NestedAppOperatingContext(configuration); @@ -389,10 +392,9 @@ export async function createNestablePublicClientApplication( if (nestedAppAuth.isAvailable()) { const controller = new NestedAppAuthController(nestedAppAuth); - const nestablePCA = pcaFactory ? pcaFactory(configuration, controller) : new PublicClientApplication( - configuration, - controller - ); + const nestablePCA = pcaFactory + ? pcaFactory(configuration, controller) + : new PublicClientApplication(configuration, controller); await nestablePCA.initialize({ correlationId: cid }); return nestablePCA; } diff --git a/lib/msal-browser/test/app/createNestablePublicClientApplication.spec.ts b/lib/msal-browser/test/app/createNestablePublicClientApplication.spec.ts index 39bf9f2447..f01df6af57 100644 --- a/lib/msal-browser/test/app/createNestablePublicClientApplication.spec.ts +++ b/lib/msal-browser/test/app/createNestablePublicClientApplication.spec.ts @@ -8,10 +8,7 @@ import { createNestablePublicClientApplication, createStandardPublicClientApplication, } from "../../src/app/PublicClientApplication.js"; -import { - TEST_CONFIG, - RANDOM_TEST_GUID, -} from "../utils/StringConstants.js"; +import { TEST_CONFIG, RANDOM_TEST_GUID } from "../utils/StringConstants.js"; import { NestedAppOperatingContext } from "../../src/operatingcontext/NestedAppOperatingContext.js"; import { NestedAppAuthController } from "../../src/controllers/NestedAppAuthController.js"; import { Configuration, IPublicClientApplication } from "../../src/index.js"; @@ -52,17 +49,33 @@ describe("createNestablePublicClientApplication tests", () => { mockNestedAppAuthController = {} as any; // Mock constructors - (NestedAppOperatingContext as jest.MockedClass).mockImplementation(() => mockNestedAppOperatingContext); - (NestedAppAuthController as jest.MockedClass).mockImplementation(() => mockNestedAppAuthController); + ( + NestedAppOperatingContext as jest.MockedClass< + typeof NestedAppOperatingContext + > + ).mockImplementation(() => mockNestedAppOperatingContext); + ( + NestedAppAuthController as jest.MockedClass< + typeof NestedAppAuthController + > + ).mockImplementation(() => mockNestedAppAuthController); // Mock PublicClientApplication - jest.spyOn(PublicClientApplication.prototype, "initialize").mockResolvedValue(undefined); + jest.spyOn( + PublicClientApplication.prototype, + "initialize" + ).mockResolvedValue(undefined); // Mock createNewGuid - createNewGuidSpy = jest.spyOn(BrowserCrypto, "createNewGuid").mockReturnValue(RANDOM_TEST_GUID); + createNewGuidSpy = jest + .spyOn(BrowserCrypto, "createNewGuid") + .mockReturnValue(RANDOM_TEST_GUID); // Get the mocked function - createStandardSpy = createStandardPublicClientApplication as jest.MockedFunction; + createStandardSpy = + createStandardPublicClientApplication as jest.MockedFunction< + typeof createStandardPublicClientApplication + >; }); afterEach(() => { @@ -76,25 +89,37 @@ describe("createNestablePublicClientApplication tests", () => { describe("Without pcaFactory parameter", () => { it("should create a nestable PCA using default PublicClientApplication constructor", async () => { - const result = await createNestablePublicClientApplication(testConfig); + const result = await createNestablePublicClientApplication( + testConfig + ); // Verify NestedAppOperatingContext was created with config - expect(NestedAppOperatingContext).toHaveBeenCalledWith(testConfig); + expect(NestedAppOperatingContext).toHaveBeenCalledWith( + testConfig + ); // Verify initialize was called with generated correlation ID - expect(mockNestedAppOperatingContext.initialize).toHaveBeenCalledWith(RANDOM_TEST_GUID); + expect( + mockNestedAppOperatingContext.initialize + ).toHaveBeenCalledWith(RANDOM_TEST_GUID); // Verify isAvailable was called - expect(mockNestedAppOperatingContext.isAvailable).toHaveBeenCalled(); + expect( + mockNestedAppOperatingContext.isAvailable + ).toHaveBeenCalled(); // Verify NestedAppAuthController was created with the operating context - expect(NestedAppAuthController).toHaveBeenCalledWith(mockNestedAppOperatingContext); + expect(NestedAppAuthController).toHaveBeenCalledWith( + mockNestedAppOperatingContext + ); // Verify the result is a PublicClientApplication instance expect(result).toBeInstanceOf(PublicClientApplication); // Verify initialize was called on the PCA instance - expect(result.initialize).toHaveBeenCalledWith({ correlationId: RANDOM_TEST_GUID }); + expect(result.initialize).toHaveBeenCalledWith({ + correlationId: RANDOM_TEST_GUID, + }); }); it("should use provided correlation ID when specified", async () => { @@ -102,13 +127,20 @@ describe("createNestablePublicClientApplication tests", () => { const freshGuidSpy = jest.spyOn(BrowserCrypto, "createNewGuid"); const customCorrelationId = "custom-correlation-id"; - const result = await createNestablePublicClientApplication(testConfig, customCorrelationId); + const result = await createNestablePublicClientApplication( + testConfig, + customCorrelationId + ); // Verify initialize was called with custom correlation ID - expect(mockNestedAppOperatingContext.initialize).toHaveBeenCalledWith(customCorrelationId); + expect( + mockNestedAppOperatingContext.initialize + ).toHaveBeenCalledWith(customCorrelationId); // Verify initialize was called on PCA with custom correlation ID - expect(result.initialize).toHaveBeenCalledWith({ correlationId: customCorrelationId }); + expect(result.initialize).toHaveBeenCalledWith({ + correlationId: customCorrelationId, + }); // Verify createNewGuid was not called since correlation ID was provided expect(freshGuidSpy).not.toHaveBeenCalled(); @@ -123,7 +155,9 @@ describe("createNestablePublicClientApplication tests", () => { expect(createNewGuidSpy).toHaveBeenCalled(); // Verify initialize was called with generated ID - expect(mockNestedAppOperatingContext.initialize).toHaveBeenCalledWith(RANDOM_TEST_GUID); + expect( + mockNestedAppOperatingContext.initialize + ).toHaveBeenCalledWith(RANDOM_TEST_GUID); }); }); @@ -142,13 +176,18 @@ describe("createNestablePublicClientApplication tests", () => { ); // Verify pcaFactory was called with config and controller - expect(mockPcaFactory).toHaveBeenCalledWith(testConfig, mockNestedAppAuthController); + expect(mockPcaFactory).toHaveBeenCalledWith( + testConfig, + mockNestedAppAuthController + ); // Verify the returned PCA is the one from factory expect(result).toBe(mockPCA); // Verify initialize was called on the factory-created PCA - expect(mockPCA.initialize).toHaveBeenCalledWith({ correlationId: RANDOM_TEST_GUID }); + expect(mockPCA.initialize).toHaveBeenCalledWith({ + correlationId: RANDOM_TEST_GUID, + }); }); it("should use pcaFactory with custom correlation ID", async () => { @@ -168,10 +207,15 @@ describe("createNestablePublicClientApplication tests", () => { ); // Verify pcaFactory was called with config and controller - expect(mockPcaFactory).toHaveBeenCalledWith(testConfig, mockNestedAppAuthController); + expect(mockPcaFactory).toHaveBeenCalledWith( + testConfig, + mockNestedAppAuthController + ); // Verify initialize was called with custom correlation ID - expect(mockPCA.initialize).toHaveBeenCalledWith({ correlationId: customCorrelationId }); + expect(mockPCA.initialize).toHaveBeenCalledWith({ + correlationId: customCorrelationId, + }); // Verify createNewGuid was not called expect(freshGuidSpy).not.toHaveBeenCalled(); @@ -181,7 +225,10 @@ describe("createNestablePublicClientApplication tests", () => { it("should handle pcaFactory returning different PCA implementation", async () => { class CustomPCA implements IPublicClientApplication { - constructor(public config: Configuration, public controller: IController) {} + constructor( + public config: Configuration, + public controller: IController + ) {} initialize = jest.fn().mockResolvedValue(undefined); // Add other required methods with minimal implementations acquireTokenPopup = jest.fn(); @@ -211,9 +258,11 @@ describe("createNestablePublicClientApplication tests", () => { clearCache = jest.fn(); } - const mockPcaFactory = jest.fn().mockImplementation((config, controller) => { - return new CustomPCA(config, controller); - }); + const mockPcaFactory = jest + .fn() + .mockImplementation((config, controller) => { + return new CustomPCA(config, controller); + }); const result = await createNestablePublicClientApplication( testConfig, @@ -223,7 +272,9 @@ describe("createNestablePublicClientApplication tests", () => { // Verify result is instance of CustomPCA expect(result).toBeInstanceOf(CustomPCA); - expect(result.initialize).toHaveBeenCalledWith({ correlationId: RANDOM_TEST_GUID }); + expect(result.initialize).toHaveBeenCalledWith({ + correlationId: RANDOM_TEST_GUID, + }); }); }); }); @@ -237,11 +288,17 @@ describe("createNestablePublicClientApplication tests", () => { const mockStandardPCA = { type: "standard" } as any; createStandardSpy.mockResolvedValue(mockStandardPCA); - const result = await createNestablePublicClientApplication(testConfig); + const result = await createNestablePublicClientApplication( + testConfig + ); // Should have initialized NestedAppOperatingContext first - expect(mockNestedAppOperatingContext.initialize).toHaveBeenCalledWith(RANDOM_TEST_GUID); - expect(mockNestedAppOperatingContext.isAvailable).toHaveBeenCalled(); + expect( + mockNestedAppOperatingContext.initialize + ).toHaveBeenCalledWith(RANDOM_TEST_GUID); + expect( + mockNestedAppOperatingContext.isAvailable + ).toHaveBeenCalled(); // Should return a result (whether mocked or real) expect(result).toBeDefined(); From d45e3f5097927a7ec444e068c505de32d264b89b Mon Sep 17 00:00:00 2001 From: Konstantin Shabelko Date: Fri, 10 Oct 2025 16:34:15 -0400 Subject: [PATCH 3/5] Change files --- ...-msal-browser-e8a7eb79-1f90-43a2-8788-a2e901e835ca.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@azure-msal-browser-e8a7eb79-1f90-43a2-8788-a2e901e835ca.json diff --git a/change/@azure-msal-browser-e8a7eb79-1f90-43a2-8788-a2e901e835ca.json b/change/@azure-msal-browser-e8a7eb79-1f90-43a2-8788-a2e901e835ca.json new file mode 100644 index 0000000000..2c583784c7 --- /dev/null +++ b/change/@azure-msal-browser-e8a7eb79-1f90-43a2-8788-a2e901e835ca.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "Add PCAFactory and correlation id optional params to createNestablePublicClientApplication #8093", + "packageName": "@azure/msal-browser", + "email": "kshabelko@microsoft.com", + "dependentChangeType": "patch" +} From 00e00363b2e5f0af3d1fbb2b146949b0861bcba1 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Mon, 13 Oct 2025 11:36:48 -0400 Subject: [PATCH 4/5] Update lib/msal-browser/apiReview/msal-browser.api.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- lib/msal-browser/apiReview/msal-browser.api.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/msal-browser/apiReview/msal-browser.api.md b/lib/msal-browser/apiReview/msal-browser.api.md index 954bb26bf5..4ada98c3dd 100644 --- a/lib/msal-browser/apiReview/msal-browser.api.md +++ b/lib/msal-browser/apiReview/msal-browser.api.md @@ -489,12 +489,13 @@ export type Configuration = { // @public function createGuid(): string; -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen -// Warning: (ae-missing-release-tag) "createNestablePublicClientApplication" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public +/** + * Creates a nestable PublicClientApplication instance. + * @param configuration - The configuration object for the client application. + * @param correlationId - Optional correlation ID for tracking requests. + * @param pcaFactory - Optional factory function to customize PublicClientApplication creation. + * @public + */ export function createNestablePublicClientApplication(configuration: Configuration, correlationId?: string, pcaFactory?: (configuration: Configuration, controller: IController) => IPublicClientApplication): Promise; // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen From e94f3c6935e152de9da1de1dd1b43b9da320a804 Mon Sep 17 00:00:00 2001 From: Konstantin Shabelko Date: Mon, 13 Oct 2025 11:47:52 -0400 Subject: [PATCH 5/5] - Update API doc. --- lib/msal-browser/apiReview/msal-browser.api.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/msal-browser/apiReview/msal-browser.api.md b/lib/msal-browser/apiReview/msal-browser.api.md index 4ada98c3dd..954bb26bf5 100644 --- a/lib/msal-browser/apiReview/msal-browser.api.md +++ b/lib/msal-browser/apiReview/msal-browser.api.md @@ -489,13 +489,12 @@ export type Configuration = { // @public function createGuid(): string; -/** - * Creates a nestable PublicClientApplication instance. - * @param configuration - The configuration object for the client application. - * @param correlationId - Optional correlation ID for tracking requests. - * @param pcaFactory - Optional factory function to customize PublicClientApplication creation. - * @public - */ +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen +// Warning: (ae-missing-release-tag) "createNestablePublicClientApplication" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public export function createNestablePublicClientApplication(configuration: Configuration, correlationId?: string, pcaFactory?: (configuration: Configuration, controller: IController) => IPublicClientApplication): Promise; // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen