Skip to content

Enable MSAL broker on macOS and Linux - #4503

Draft
mdaigle wants to merge 1 commit into
mainfrom
dev/mdaigle/macos-broker
Draft

Enable MSAL broker on macOS and Linux#4503
mdaigle wants to merge 1 commit into
mainfrom
dev/mdaigle/macos-broker

Conversation

@mdaigle

@mdaigle mdaigle commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Extends the recently added Windows broker support to macOS and Linux via BrokerOptions.OperatingSystems.Linux and .OSX. The broker is force-enabled for the SqlClient first-party app id, matching existing Windows behavior. Custom app ids continue to opt in through UseWamBroker.

Redirect URIs

MSAL forwards the app-configured redirect URI straight to msalruntime, so it has to be correct per platform. WamAdapters.GetExpectedRedirectUri is dead code in 4.84.2 and does not fix this up.

Platform URI
Windows / WSL ms-appx-web://microsoft.aad.brokerplugin/{clientId}
Linux https://login.microsoftonline.com/common/oauth2/nativeclient
macOS, bundled msauth.{CFBundleIdentifier}://auth
macOS, not bundled msauth.com.msauth.unsignedapp://auth

Values come from the macOS and Linux broker docs.

Platform guards

macOS. The broker is enabled for all hosts. A bundled app running on the default app id throws, because its redirect URI derives from the host's bundle identifier and cannot be registered on the first-party app. Device code flow is exempt, since DeviceCodeRequest never consults the broker and SilentRequest skips it for accounts sourced from that flow.

Linux. Gated on x64, non-musl, plus a NativeLibrary.TryLoad probe. Without the probe, hosts missing libwebkit2gtk, libsecret, or libX11 fail hard with wam_runtime_init_failed, as RuntimeBroker offers no browser fallback. With it, they degrade to the browser.

Platform detection is lazy, so managed identity, workload identity, service principal, and default credential flows never load the native library.

Behavioral changes

  • Bundled macOS GUI apps on the default app id now throw. There is no opt-out short of supplying an ApplicationClientId or using device code flow.
  • macOS terminal apps need MacMainThreadScheduler for ActiveDirectoryInteractive; MSAL throws wam_ui_thread off thread 1. Silent and integrated flows are unaffected.
  • Unenrolled Macs no longer fall back to the browser for ActiveDirectoryInteractive.

Also

AuthenticationException's two-argument constructor now chains to the six-parameter base so Method survives into SqlError.Procedure instead of reading NotSpecified.

Blocker before merge

The first-party app registration 2fd908ad-0664-4344-b9be-cd3e8b574c38 needs https://login.microsoftonline.com/common/oauth2/nativeclient explicitly enabled and msauth.com.msauth.unsignedapp://auth added. Without both, Linux and macOS fail at the broker. This cannot be verified from the repo and needs someone with access to the registration.

Testing

WamBrokerTests expanded from 18 to 29 tests, passing on net8.0/9.0/10.0. Interop and native-load behavior was verified empirically rather than inferred: bundle-id lookup against a real .app bundle and a loose executable, the reflective NativeLibrary.TryLoad path returning a live handle, and NativeInterop 0.20.6 decompiled to confirm the arch-specific library name and that its Linux preload path is unreachable. The Method regression test was confirmed to fail against the old constructor.

Two Azure.Test failures (AADConnectionTest.ADIntegratedUsingSSPI, ActiveDirectoryInteractiveTests.TestConnection) are pre-existing and need a live server or Windows SSPI.

  • Tests added or updated
  • Public API changes documented
  • Verified against customer repro
  • Ensure no breaking changes introduced (see Behavioral changes)

Extends broker support beyond Windows via BrokerOptions.OperatingSystems.Linux
and .OSX, force-enabled for the SqlClient first-party app id to match the
existing Windows behavior. Custom app ids continue to opt in with UseWamBroker.

Redirect URIs are now selected per platform, since the broker forwards the
app-configured URI straight to msalruntime:

  Windows             ms-appx-web://microsoft.aad.brokerplugin/{clientId}
  Linux               https://login.microsoftonline.com/common/oauth2/nativeclient
  macOS bundled       msauth.{CFBundleIdentifier}://auth
  macOS non-bundled   msauth.com.msauth.unsignedapp://auth

Platform guards:

  * macOS bundled apps on the default app id throw, because the derived URI
    cannot be registered on the first-party app. Device code flow is exempt as
    it never consults the broker.
  * Linux is gated on x64, non-musl, and a NativeLibrary.TryLoad probe, so
    hosts missing libwebkit2gtk/libsecret/libX11 fall back to the browser
    rather than failing with wam_runtime_init_failed.

Detection is lazy so managed identity, workload identity, service principal,
and default credential flows never load the native library.

AuthenticationException's two-arg constructor now chains to the six-parameter
base so Method survives into SqlError.Procedure.

Behavioral changes: bundled macOS GUI apps on the default app id now throw;
macOS terminal apps need MacMainThreadScheduler for ActiveDirectoryInteractive;
unenrolled Macs no longer get a browser fallback for that flow.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 4, 2026 22:13
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Aug 4, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Extends ActiveDirectoryAuthenticationProvider brokered authentication beyond Windows to also support macOS and Linux (where MSAL’s native broker runtime is available), including platform-specific redirect URI selection and expanded test coverage.

Changes:

  • Added cross-platform broker detection/guardrails (Windows/macOS/Linux) and centralized redirect URI selection via a new broker-specific partial class.
  • Introduced macOS bundle identifier detection to compute the broker redirect URI for bundled apps, with documented/validated behavior differences.
  • Expanded WamBrokerTests to cover platform support detection, redirect URI selection, and an AuthenticationException constructor regression.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs Updates comments to reflect “brokering where supported” (not Windows-only).
src/Microsoft.Data.SqlClient.Extensions/Azure/test/WamBrokerTests.cs Adds tests for broker OS detection, redirect URI selection, and exception constructor behavior.
src/Microsoft.Data.SqlClient.Extensions/Azure/src/Interop/Interop.NSBundle.cs Adds macOS Objective-C interop to resolve the host bundle identifier.
src/Microsoft.Data.SqlClient.Extensions/Azure/src/AuthenticationException.cs Fixes 2-arg ctor chaining so Method is preserved on the exception object.
src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.Windows.cs Updates Windows-specific documentation to reflect cross-platform broker support.
src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs Refactors to use centralized redirect URI logic and enables broker across supported OSes.
src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.Broker.cs New: broker platform detection, Linux native runtime probe, and redirect URI resolution.
src/Microsoft.Data.SqlClient.Extensions/Azure/doc/ActiveDirectoryAuthenticationProviderOptions.xml Updates docs for broker behavior/redirect URIs and platform requirements.
src/Microsoft.Data.SqlClient.Extensions/Azure/doc/ActiveDirectoryAuthenticationProvider.xml Updates docs for parent window callback behavior with brokers on non-Windows.

Comment on lines +254 to +256
object?[] arguments = new object?[] { LinuxMsalRuntimeLibraryName, nativeInterop, null, null };

return tryLoad.Invoke(null, arguments) is true;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: To triage

Development

Successfully merging this pull request may close these issues.

2 participants