feat: macOS brokered authentication support#452
Draft
dggsax wants to merge 11 commits intoAzureAD:mainfrom
Draft
feat: macOS brokered authentication support#452dggsax wants to merge 11 commits intoAzureAD:mainfrom
dggsax wants to merge 11 commits intoAzureAD:mainfrom
Conversation
Add support for macOS Enterprise SSO Extension brokered authentication, bringing feature parity with Windows WAM broker support. Key changes: - Upgrade MSAL 4.65.0 → 4.83.1, add NativeInterop v0.20.3 - Extend Broker auth flow with macOS-specific PCA config, account resolution, and browser fallback - Add DefaultAccountStore to persist account username for silent auth (OperatingSystemAccount not supported on macOS) - Add MacMainThreadScheduler message loop in Program.cs - Extend AuthMode enum and CLI parsing to support broker on macOS - Update docs with macOS broker prerequisites and redirect URI config Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Skip macOS broker auth if Company Portal is not installed or is below version 2603 (which added redirect_uri validation fix for unsigned apps). Falls back to web auth transparently in those cases. - Add IsMacOSBrokerAvailable() to IPlatformUtils/PlatformUtils - AuthFlowFactory uses IsMacOSBrokerAvailable() as gatekeeper - Broker.cs still uses IsMacOS() for runtime behavior (fallback, persist) - Reads CP version from Info.plist via 'defaults read' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
On macOS, broker is no longer included in default auth modes. Users must explicitly pass '--mode broker' to use it. If broker is requested but Company Portal >= 5.2603.0 is not installed, AuthFlowFactory throws a clear InvalidOperationException instead of silently falling through to web auth (which hangs for apps with broker-required CA policies like token protection). - AuthMode.Default on non-Windows: Broker|Web -> Web - AuthFlowFactory: explicit error when broker requested but CP unavailable - New test: BrokerRequested_Mac_CP_Unavailable_Throws Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Include CP path in broker unavailable error message - Add trace-level logging: CP path, raw version output, stderr, parsed version parts (major/release/build) - Expose CompanyPortalAppPath as public const for error messages - Update test script to reflect broker-opt-in behavior: new tests for broker+web combined, trace diagnostics, reordered Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The macOS broker requires AcquireTokenInteractive to run on the main thread. Program.cs starts the MacMainThreadScheduler message loop on main and dispatches CLI work to Task.Run, but the broker interactive calls were still executing on the background thread. Now GetTokenInteractive/WithClaims dispatch through MacMainThreadScheduler.RunOnMainThreadAsync when running on macOS with the scheduler active (IsRunning check prevents deadlock in tests). Also: improved CP diagnostics trace logging and included CP path in the broker unavailable error message. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Check 'app-sso -l' for registered Enterprise SSO Extensions before attempting broker auth. If no extensions are registered (MDM profile not applied), gives a clear error instead of a cryptic broker failure. Designed for easy revert: - Set AZUREAUTH_SKIP_SSO_CHECK=1 to bypass the check entirely - If app-sso fails or isn't available, assumes broker may work (non-fatal) - The check is a single method call in CheckMacOSBrokerAvailable() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move test-macos-broker.sh and swap-cp.sh from repo root to bin/mac/ alongside existing macOS build scripts. Update REPO_ROOT to resolve two levels up from the new location. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add AZUREAUTH_TEST_VERBOSITY env var (default: debug) to control log level across all tests (Test 3 always uses trace) - Comment out SSO Extension check (confirmed unnecessary for broker) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Match the existing Windows pattern where broker is silently skipped on unsupported platforms (e.g., Windows Server). On macOS, if broker is requested but Company Portal is insufficient, log a warning and continue to the next flow (Web, DeviceCode, etc.) instead of throwing. This means '--mode broker --mode web' will fall through to web when CP is unavailable, and '--mode broker' alone will try CachedAuth only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Web auth hangs for this broker-required app (token protection CA policy), so comment out Tests 2 and 5. Add cache clear + broker interactive re-prompt cycle (Tests 6-8) to verify full broker lifecycle: authenticate → clear → re-authenticate. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ChristopherJMiller
requested changes
Apr 9, 2026
Contributor
There was a problem hiding this comment.
can this script have a comment at the top describing what it's for testing wise and why it's needed?
| --resource "$RESOURCE" \ | ||
| --mode broker --output json --verbosity "$VERBOSITY" | ||
|
|
||
| # ── Test 2: Broker + web combined — COMMENTED OUT ───────────── |
Contributor
There was a problem hiding this comment.
for a checked in testing suite is it worth keeping this commented out test?
|
|
||
| var subject = new[] { AuthMode.Web, AuthMode.DeviceCode }; | ||
| // Default on macOS is Web only (broker is opt-in). | ||
| var subject = new[] { AuthMode.Web }; |
Contributor
There was a problem hiding this comment.
should this be an os specific test?
| return false; | ||
| } | ||
|
|
||
| // TODO: Re-enable once we confirm SSO Extension registration is required. |
Contributor
There was a problem hiding this comment.
we may want to track this in an issue so it's not forgotten about
| #else | ||
| public const string AuthModeHelperText = $@"Authentication mode. Repeated invocations allowed | ||
| [default: web] | ||
| [default: broker, then web] |
Contributor
There was a problem hiding this comment.
just like windows it has condition -
#if PlatformWindows
[default: broker, then web]
can we add the same for MAC ?
broker may impact linux machines
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 macOS brokered authentication support via MSAL.NET, NativeInterop, and the macOS Enterprise SSO Extension (deployed through Company Portal).
What this does
--mode broker. Supports interactive broker (first run) and silent broker (subsequent runs via persisted account).MacMainThreadScheduler, as required by MSAL on macOS.DefaultAccountStorepersists the authenticated username to~/.azureauth/default_account_{tenant}_{client}.jsonfor silent re-auth (sinceOperatingSystemAccountis not supported on macOS).--mode broker --mode webare specified, falls back to browser auth if broker fails.Key design decisions
--mode broker) — apps with broker-required Conditional Access policies (token protection, error 530084) will hang indefinitely on web auth, so we do not include broker in the default mode.OperatingSystemAccount— this Windows-only concept does not work on macOS. We persist the username and look up theIAccountfrom the MSAL cache instead.app-sso -lreturned empty on test devices yet broker worked fine. The check is kept as commented-out code for future investigation.Testing
DefaultAccountStoreTest(8 tests),BrokerMacOSTest(6 tests)bin/mac/test-macos-broker.shFiles changed
New files:
src/MSALWrapper/DefaultAccountStore.cs— account username persistencesrc/MSALWrapper.Test/DefaultAccountStoreTest.cs— 8 unit testssrc/MSALWrapper.Test/AuthFlow/BrokerMacOSTest.cs— 6 unit testsbin/mac/test-macos-broker.sh— functional test scriptbin/mac/swap-cp.sh— CP version swap utility for testingModified files:
src/MSALWrapper/MSALWrapper.csproj— NuGet upgradessrc/MSALWrapper/AuthFlow/Broker.cs— major rewrite for cross-platformsrc/MSALWrapper/AuthFlow/AuthFlowFactory.cs— broker availability gatingsrc/MSALWrapper/PlatformUtils.cs— CP version detection, macOS checkssrc/MSALWrapper/AuthMode.cs— broker opt-in on non-Windowssrc/MSALWrapper/Constants.cs— macOS broker redirect URIsrc/AzureAuth/Program.cs— main thread scheduler patternsrc/AzureAuth/Commands/CommandAad.cs—--mode brokeroptiondocs/usage.md— macOS broker prerequisites and redirect URI configREADME.md— feature matrix updatedPrerequisites for broker auth
msauth.com.msauth.unsignedapp://auth