Add Nested App Authentication (NAA) bridge for MSAL v5 extensions#138
Merged
Conversation
Implements the client-side NAA bridge shim that enables Azure DevOps extensions to use MSAL v5's createNestablePublicClientApplication for authentication. Extensions running in cross-origin iframes cannot use MSAL v5's BroadcastChannel-based redirect flow due to browser storage partitioning. The NAA bridge solves this by delegating token acquisition to the host frame. The shim translates between MSAL's event-based postMessage/addEventListener API (window.nestedAppAuthBridge) and the host frame's XDM-based processRequest method (DevOps.NestedAppAuth). The bridge is initialized automatically after SDK.init() completes. If the host does not support NAA (feature flag off), initialization is silently skipped. Companion change in the ADO monorepo: PR #920218 (host-side bridge handler) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Instead of auto-initializing the bridge for every extension, expose SDK.enableNestedAppAuth() that extensions call explicitly. This avoids unnecessary XDM traffic for extensions that don't need NAA, and gives extensions a clear error if the host doesn't support it (missing entraClientId or feature flag off). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…docs - Replace getRemoteObjectProxy with invokeRemoteMethod for XDM calls (host-side serializer does not proxy functions across the boundary) - Add Ping-based availability check during bridge initialization - Update error message (removed entraClientId reference) - Fix indentation in bridge object literal - Add Nested App Authentication section to README with usage guide Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
clairebaire
reviewed
May 14, 2026
- Improve error message to 'not available in this Azure DevOps environment yet' (Claire's feedback) - Add disableNestedAppAuth() + teardownNestedAppAuthBridge() for cleanup (Claire's feedback) - Fix 'ADO' abbreviation in README Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bc6ddfc to
4428375
Compare
After disableNestedAppAuth(), replace window.nestedAppAuthBridge with a stub whose postMessage/addEventListener throw a clear error instead of deleting the property. This prevents MSAL from silently falling back to the broken popup redirect flow when the bridge is disabled. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
4428375 to
9acf17e
Compare
clairebaire
approved these changes
May 14, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The poisoned bridge was replacing the entire window.nestedAppAuthBridge object, which orphaned MSAL's listener that was registered via addEventListener on the original object. This caused acquireTokenPopup to hang after disableNestedAppAuth() — the poisoned response was delivered to an empty listeners array. Fix: store listeners in a _naaListeners property on the bridge object during initialization, and have teardown mutate only the postMessage function in-place. This way existing MSAL listeners continue to receive responses (now poisoned BridgeDisabled errors). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
clairebaire
approved these changes
May 14, 2026
Document that acquireTokenSilent will fail with consent_required on first use, and that the InteractionRequiredAuthError fallback handles this automatically via popup. Also document explicit consent prompt and admin consent for elevated permissions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
dpaquette
approved these changes
Jun 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Nested App Authentication (NAA) support to the Azure DevOps extension SDK, enabling extensions to use MSAL v5's
createNestablePublicClientApplicationfor authentication in cross-origin iframes.Problem
Extensions running in cross-origin iframes cannot use MSAL v5's BroadcastChannel-based redirect flow due to browser storage partitioning -- the popup and iframe cannot communicate across partitions.
Solution
The NAA bridge delegates token acquisition to the host frame, where the MSAL PublicClientApplication runs in the top-level browsing context without partitioning issues.
Extensions opt in by calling
SDK.enableNestedAppAuth()afterSDK.init(). This sets upwindow.nestedAppAuthBridge, which MSAL'screateNestablePublicClientApplicationdiscovers automatically.How it works
SDK.enableNestedAppAuth()afterSDK.init()DevOps.NestedAppAuthremote proxy from the host via XDMwindow.nestedAppAuthBridgewithaddEventListener/postMessage(the interface MSAL expects)postMessage(requestJson), the shim forwards it to the host via XDMIf the host doesn't support NAA,
enableNestedAppAuth()throws with a clear error message.Files changed
src/NestedAppAuthBridge.ts(new) -- Bridge shim implementationsrc/SDK.ts-- ExportsenableNestedAppAuth()anddisableNestedAppAuth()functionsExtension usage
Prerequisites
https://dev.azure.com/_public/_MsalPopup