From 461a417aad8a04f72c49fe79c8ca98f8e394e124 Mon Sep 17 00:00:00 2001 From: Ashok Kumar Ramakrishnan <83938949+ashok672@users.noreply.github.com> Date: Mon, 8 Jun 2026 16:14:36 -0700 Subject: [PATCH 1/5] Disable broker on Intel-based Macs Broker on macOS is supported only on Apple Silicon (arm64). On Intel Macs (x86_64 / i386) MSAL Python will now force-disable broker in ClientApplication._decide_broker, regardless of whether a broker is installed on the device or whether the app opted in via enable_broker_on_mac=True. Apple Silicon Macs and all non-Mac platforms are unaffected. The check sits in the single broker-decision chokepoint and reuses the existing 'broker unavailable, falling back to non-broker' warning path. Tests: - tests/test_application.py::TestBrokerDisabledOnIntelMac covers the three architecture branches (arm64, x86_64, i386) by patching sys.platform and platform.machine, matching the existing broker-test pattern in this file. CI runs on ubuntu-latest only, so the mock is the only way to exercise the darwin branch. - tests/intel_mac_broker_smoke_test.py is a credential-free, no-UI manual smoke test that runs in a few seconds on real hardware (especially useful on an Intel Mac, which CI cannot cover). --- msal/application.py | 13 +++++ tests/intel_mac_broker_smoke_test.py | 73 ++++++++++++++++++++++++++++ tests/test_application.py | 38 +++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 tests/intel_mac_broker_smoke_test.py diff --git a/msal/application.py b/msal/application.py index d15a4b7e..a3d92591 100644 --- a/msal/application.py +++ b/msal/application.py @@ -2,6 +2,7 @@ import json import time import logging +import platform import sys import warnings from threading import Lock @@ -763,6 +764,18 @@ def _decide_broker(self, allow_broker, enable_pii_log): and not self.authority.is_adfs and not self.authority._is_b2c ) + if ( + self._enable_broker + and sys.platform == "darwin" + and platform.machine() in ("x86_64", "i386") + ): + # Broker on macOS is supported only on Apple Silicon (arm64). + # Intel Macs are excluded by product policy, regardless of whether + # a broker is actually installed on the device. + self._enable_broker = False + logger.warning( + "Broker is not supported on Intel-based Macs. " + "We will fallback to non-broker.") if self._enable_broker: try: _init_broker(enable_pii_log) diff --git a/tests/intel_mac_broker_smoke_test.py b/tests/intel_mac_broker_smoke_test.py new file mode 100644 index 00000000..458c51e3 --- /dev/null +++ b/tests/intel_mac_broker_smoke_test.py @@ -0,0 +1,73 @@ +"""Manual smoke test for the Intel-Mac broker-disable gate. + +This script is intentionally credential-free and runs in a few seconds. +It exercises the production decision logic in ``ClientApplication._decide_broker`` +on real hardware (no mocks), which is the one thing the unit tests in +``test_application.py::TestBrokerDisabledOnIntelMac`` cannot do — CI runs on +``ubuntu-latest`` only, so ``sys.platform`` is patched there. + +How to run:: + + pip install --force-reinstall "msal[broker]" # or your local checkout + python tests/intel_mac_broker_smoke_test.py + +Expected outcomes: + +* Apple Silicon Mac (``arm64``) with ``pymsalruntime`` installed: + ``_enable_broker`` is ``True``. +* Intel Mac (``x86_64`` / ``i386``): + ``_enable_broker`` is ``False`` even though the opt-in was passed and even + if a broker is installed on the device. +* Non-Mac (Windows, Linux): + ``enable_broker_on_mac`` is ignored — ``_enable_broker`` is ``False``. + +The script asserts the expected outcome for the host it runs on and exits +non-zero if the gate misbehaves. +""" +import platform +import sys + +import msal + + +_CLIENT_ID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46" # Azure CLI, public +_AUTHORITY = "https://login.microsoftonline.com/organizations" + + +def _expected_broker_state(): + if sys.platform != "darwin": + return False, "non-Mac platform — enable_broker_on_mac is a no-op" + if platform.machine() in ("x86_64", "i386"): + return False, "Intel Mac — broker disabled by product policy" + return True, "Apple Silicon Mac — broker should be enabled" + + +def main(): + print(f"sys.platform = {sys.platform!r}") + print(f"platform.machine() = {platform.machine()!r}") + + expected, why = _expected_broker_state() + print(f"Expected _enable_broker = {expected} ({why})") + + app = msal.PublicClientApplication( + _CLIENT_ID, + authority=_AUTHORITY, + enable_broker_on_mac=True, + enable_broker_on_windows=True, + enable_broker_on_linux=True, + ) + actual = bool(app._enable_broker) + print(f"Actual _enable_broker = {actual}") + + if actual != expected: + print( + "FAIL: Intel-Mac gate misbehaved. " + "See ClientApplication._decide_broker in msal/application.py.", + file=sys.stderr, + ) + sys.exit(1) + print("PASS") + + +if __name__ == "__main__": + main() diff --git a/tests/test_application.py b/tests/test_application.py index 31f77a71..e0abf43a 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -1141,6 +1141,44 @@ def test_app_did_not_register_redirect_uri_should_error_out(self): self.assertEqual(result.get("error"), "broker_error") +@patch("sys.platform", new="darwin") # Pretend running on Mac. +@patch("msal.authority.tenant_discovery", new=Mock(return_value={ + "authorization_endpoint": "https://contoso.com/placeholder", + "token_endpoint": "https://contoso.com/placeholder", + "issuer": "https://contoso.com/placeholder", + })) +@patch("msal.application._init_broker", new=Mock()) # Pretend pymsalruntime installed and working +class TestBrokerDisabledOnIntelMac(unittest.TestCase): + """Broker is disabled on Intel-based Macs regardless of opt-in.""" + + @patch("msal.application.platform.machine", new=Mock(return_value="arm64")) + def test_broker_should_be_enabled_on_apple_silicon_mac(self): + app = msal.PublicClientApplication( + "client_id", + authority="https://login.microsoftonline.com/common", + enable_broker_on_mac=True, + ) + self.assertTrue(app._enable_broker) + + @patch("msal.application.platform.machine", new=Mock(return_value="x86_64")) + def test_broker_should_be_disabled_on_x86_64_mac(self): + app = msal.PublicClientApplication( + "client_id", + authority="https://login.microsoftonline.com/common", + enable_broker_on_mac=True, + ) + self.assertFalse(app._enable_broker) + + @patch("msal.application.platform.machine", new=Mock(return_value="i386")) + def test_broker_should_be_disabled_on_i386_mac(self): + app = msal.PublicClientApplication( + "client_id", + authority="https://login.microsoftonline.com/common", + enable_broker_on_mac=True, + ) + self.assertFalse(app._enable_broker) + + class MismatchingScopeTestCase(unittest.TestCase): """Test cache behavior when HTTP response scope differs from requested scope""" From bc1de09b213871883492773f8e5b28ff4c1809c2 Mon Sep 17 00:00:00 2001 From: Ashok Kumar Ramakrishnan <83938949+ashok672@users.noreply.github.com> Date: Thu, 3 Sep 2026 10:07:05 -0700 Subject: [PATCH 2/5] Fix existing broker tests to pretend Apple Silicon The new Intel-Mac gate reads platform.machine(). Existing tests patch sys.platform to darwin but ran on x86_64 CI runners, so the gate disabled the broker and four tests failed. Patch platform.machine() to arm64 so those Mac scenarios are hardware-independent. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- tests/test_application.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_application.py b/tests/test_application.py index e0abf43a..54a0b78a 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -1014,6 +1014,8 @@ def test_client_id_should_be_a_valid_scope(self): @patch("sys.platform", new="darwin") # Pretend running on Mac. +@patch("msal.application.platform.machine", new=Mock(return_value="arm64")) +# Pretend Apple Silicon, because broker is not supported on Intel-based Macs. @patch("msal.authority.tenant_discovery", new=Mock(return_value={ "authorization_endpoint": "https://contoso.com/placeholder", "token_endpoint": "https://contoso.com/placeholder", @@ -1056,6 +1058,8 @@ def test_should_fallback_when_pymsalruntime_failed_to_initialize_broker(self): @patch("sys.platform", new="darwin") # Pretend running on Mac. +@patch("msal.application.platform.machine", new=Mock(return_value="arm64")) +# Pretend Apple Silicon, because broker is not supported on Intel-based Macs. @patch("msal.authority.tenant_discovery", new=Mock(return_value={ "authorization_endpoint": "https://contoso.com/placeholder", "token_endpoint": "https://contoso.com/placeholder", From a79cb99f474117dceb482d4aa91e2bbd1d0389c1 Mon Sep 17 00:00:00 2001 From: Ashok Kumar Ramakrishnan <83938949+ashok672@users.noreply.github.com> Date: Thu, 3 Sep 2026 12:09:02 -0700 Subject: [PATCH 3/5] Address review feedback on Intel-Mac broker gate - Document that enable_broker_on_mac requires Apple Silicon (arm64) and that Intel Macs fall back to non-broker. - Smoke test: opt in only via enable_broker_on_mac, so the script no longer reports a false failure on Windows/Linux hosts where the broker prerequisites are met. - Keep the decorator stack contiguous by moving the explanatory comment onto the decorator line it describes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- msal/application.py | 7 +++++-- tests/intel_mac_broker_smoke_test.py | 4 +--- tests/test_application.py | 6 ++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/msal/application.py b/msal/application.py index 2140e471..b95a795a 100644 --- a/msal/application.py +++ b/msal/application.py @@ -2187,7 +2187,7 @@ def __init__( +--------------------------+-----------------------------------+------------------------------------------------------------------------------------+ | enable_broker_on_wsl | WSL | ms-appx-web://Microsoft.AAD.BrokerPlugin/your_client_id | +--------------------------+-----------------------------------+------------------------------------------------------------------------------------+ - | enable_broker_on_mac | Mac with Company Portal installed | msauth.com.msauth.unsignedapp://auth | + | enable_broker_on_mac | Apple Silicon Mac, Company Portal | msauth.com.msauth.unsignedapp://auth | +--------------------------+-----------------------------------+------------------------------------------------------------------------------------+ | enable_broker_on_linux | Linux with Intune installed | ``https://login.microsoftonline.com/common/oauth2/nativeclient`` (MUST be enabled) | +--------------------------+-----------------------------------+------------------------------------------------------------------------------------+ @@ -2227,7 +2227,10 @@ def __init__( New in MSAL Python 1.25.0. :param boolean enable_broker_on_mac: - This setting is only effective if your app is running on Mac. + This setting is only effective if your app is running on + an Apple Silicon (arm64) Mac. + Broker is not supported on Intel-based Macs, where this setting + is ignored and MSAL will fall back to non-broker. This parameter defaults to None, which means MSAL will not utilize a broker. New in MSAL Python 1.31.0. diff --git a/tests/intel_mac_broker_smoke_test.py b/tests/intel_mac_broker_smoke_test.py index 458c51e3..34982a61 100644 --- a/tests/intel_mac_broker_smoke_test.py +++ b/tests/intel_mac_broker_smoke_test.py @@ -52,9 +52,7 @@ def main(): app = msal.PublicClientApplication( _CLIENT_ID, authority=_AUTHORITY, - enable_broker_on_mac=True, - enable_broker_on_windows=True, - enable_broker_on_linux=True, + enable_broker_on_mac=True, # Only opt in on Mac; this script validates the Mac gate. ) actual = bool(app._enable_broker) print(f"Actual _enable_broker = {actual}") diff --git a/tests/test_application.py b/tests/test_application.py index 2b490c7d..9dfa549e 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -1621,8 +1621,7 @@ def test_client_id_should_be_a_valid_scope(self): @patch("sys.platform", new="darwin") # Pretend running on Mac. -@patch("msal.application.platform.machine", new=Mock(return_value="arm64")) -# Pretend Apple Silicon, because broker is not supported on Intel-based Macs. +@patch("msal.application.platform.machine", new=Mock(return_value="arm64")) # Pretend Apple Silicon, because broker is not supported on Intel-based Macs. @patch("msal.authority.tenant_discovery", new=Mock(return_value={ "authorization_endpoint": "https://contoso.com/placeholder", "token_endpoint": "https://contoso.com/placeholder", @@ -1665,8 +1664,7 @@ def test_should_fallback_when_pymsalruntime_failed_to_initialize_broker(self): @patch("sys.platform", new="darwin") # Pretend running on Mac. -@patch("msal.application.platform.machine", new=Mock(return_value="arm64")) -# Pretend Apple Silicon, because broker is not supported on Intel-based Macs. +@patch("msal.application.platform.machine", new=Mock(return_value="arm64")) # Pretend Apple Silicon, because broker is not supported on Intel-based Macs. @patch("msal.authority.tenant_discovery", new=Mock(return_value={ "authorization_endpoint": "https://contoso.com/placeholder", "token_endpoint": "https://contoso.com/placeholder", From 84ca9b732eb0ee97b05e6ee34b0a4481312a1b48 Mon Sep 17 00:00:00 2001 From: Ashok Kumar Ramakrishnan <83938949+ashok672@users.noreply.github.com> Date: Thu, 3 Sep 2026 13:45:11 -0700 Subject: [PATCH 4/5] Make the macOS broker gate an arm64 allowlist Previously the gate denied a fixed list of Intel architectures. Invert it so the broker is enabled only on a recognized Apple Silicon (arm64) machine, and any unexpected darwin architecture errs on the side of not using the broker. Mirror the same rule in the manual smoke test. Also restore the 'installed' qualifier on the macOS opt-in table row, widening the column so the row stays consistent with the others. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- msal/application.py | 31 +++++++++++++++------------- tests/intel_mac_broker_smoke_test.py | 7 ++++--- tests/test_application.py | 10 +++++++++ 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/msal/application.py b/msal/application.py index b95a795a..e5c032c8 100644 --- a/msal/application.py +++ b/msal/application.py @@ -819,11 +819,14 @@ def _decide_broker(self, allow_broker, enable_pii_log): if ( self._enable_broker and sys.platform == "darwin" - and platform.machine() in ("x86_64", "i386") + and platform.machine() != "arm64" ): # Broker on macOS is supported only on Apple Silicon (arm64). - # Intel Macs are excluded by product policy, regardless of whether - # a broker is actually installed on the device. + # Anything else on darwin -- Intel Macs, and an x86_64 Python + # running under Rosetta -- is excluded by product policy, + # regardless of whether a broker is installed on the device. + # This is an allowlist so that an unrecognized architecture + # errs on the side of not using the broker. self._enable_broker = False logger.warning( "Broker is not supported on Intel-based Macs. " @@ -2180,17 +2183,17 @@ def __init__( 1. You can set any combination of the following opt-in parameters to true: - +--------------------------+-----------------------------------+------------------------------------------------------------------------------------+ - | Opt-in flag | If app will run on | App has registered this as a Desktop platform redirect URI in Azure Portal | - +==========================+===================================+====================================================================================+ - | enable_broker_on_windows | Windows 10+ | ms-appx-web://Microsoft.AAD.BrokerPlugin/your_client_id | - +--------------------------+-----------------------------------+------------------------------------------------------------------------------------+ - | enable_broker_on_wsl | WSL | ms-appx-web://Microsoft.AAD.BrokerPlugin/your_client_id | - +--------------------------+-----------------------------------+------------------------------------------------------------------------------------+ - | enable_broker_on_mac | Apple Silicon Mac, Company Portal | msauth.com.msauth.unsignedapp://auth | - +--------------------------+-----------------------------------+------------------------------------------------------------------------------------+ - | enable_broker_on_linux | Linux with Intune installed | ``https://login.microsoftonline.com/common/oauth2/nativeclient`` (MUST be enabled) | - +--------------------------+-----------------------------------+------------------------------------------------------------------------------------+ + +--------------------------+-------------------------------------------------+------------------------------------------------------------------------------------+ + | Opt-in flag | If app will run on | App has registered this as a Desktop platform redirect URI in Azure Portal | + +==========================+=================================================+====================================================================================+ + | enable_broker_on_windows | Windows 10+ | ms-appx-web://Microsoft.AAD.BrokerPlugin/your_client_id | + +--------------------------+-------------------------------------------------+------------------------------------------------------------------------------------+ + | enable_broker_on_wsl | WSL | ms-appx-web://Microsoft.AAD.BrokerPlugin/your_client_id | + +--------------------------+-------------------------------------------------+------------------------------------------------------------------------------------+ + | enable_broker_on_mac | Apple Silicon Mac with Company Portal installed | msauth.com.msauth.unsignedapp://auth | + +--------------------------+-------------------------------------------------+------------------------------------------------------------------------------------+ + | enable_broker_on_linux | Linux with Intune installed | ``https://login.microsoftonline.com/common/oauth2/nativeclient`` (MUST be enabled) | + +--------------------------+-------------------------------------------------+------------------------------------------------------------------------------------+ 2. Install broker dependency, e.g. ``pip install msal[broker]>=1.33,<2``. diff --git a/tests/intel_mac_broker_smoke_test.py b/tests/intel_mac_broker_smoke_test.py index 34982a61..b2560eac 100644 --- a/tests/intel_mac_broker_smoke_test.py +++ b/tests/intel_mac_broker_smoke_test.py @@ -15,7 +15,8 @@ * Apple Silicon Mac (``arm64``) with ``pymsalruntime`` installed: ``_enable_broker`` is ``True``. -* Intel Mac (``x86_64`` / ``i386``): +* Intel Mac (``x86_64`` / ``i386``), or any other non-``arm64`` machine + (including an ``x86_64`` Python running under Rosetta): ``_enable_broker`` is ``False`` even though the opt-in was passed and even if a broker is installed on the device. * Non-Mac (Windows, Linux): @@ -37,8 +38,8 @@ def _expected_broker_state(): if sys.platform != "darwin": return False, "non-Mac platform — enable_broker_on_mac is a no-op" - if platform.machine() in ("x86_64", "i386"): - return False, "Intel Mac — broker disabled by product policy" + if platform.machine() != "arm64": + return False, "not Apple Silicon — broker disabled by product policy" return True, "Apple Silicon Mac — broker should be enabled" diff --git a/tests/test_application.py b/tests/test_application.py index 9dfa549e..7e5a64dd 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -1787,6 +1787,16 @@ def test_broker_should_be_disabled_on_i386_mac(self): ) self.assertFalse(app._enable_broker) + @patch("msal.application.platform.machine", new=Mock(return_value="unexpected")) + def test_broker_should_be_disabled_on_unrecognized_machine(self): + """The gate is an allowlist, so an unknown architecture stays broker-free.""" + app = msal.PublicClientApplication( + "client_id", + authority="https://login.microsoftonline.com/common", + enable_broker_on_mac=True, + ) + self.assertFalse(app._enable_broker) + class MismatchingScopeTestCase(unittest.TestCase): """Test cache behavior when HTTP response scope differs from requested scope""" From f4edfe384e89efd796733b18e646ed752f2ebbfd Mon Sep 17 00:00:00 2001 From: Ashok Kumar Ramakrishnan <83938949+ashok672@users.noreply.github.com> Date: Thu, 3 Sep 2026 13:54:05 -0700 Subject: [PATCH 5/5] Update warning message for broker support on macOS Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- msal/application.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msal/application.py b/msal/application.py index e5c032c8..1aa14c28 100644 --- a/msal/application.py +++ b/msal/application.py @@ -829,7 +829,7 @@ def _decide_broker(self, allow_broker, enable_pii_log): # errs on the side of not using the broker. self._enable_broker = False logger.warning( - "Broker is not supported on Intel-based Macs. " + "Broker on macOS is supported only on Apple Silicon (arm64). " "We will fallback to non-broker.") if self._enable_broker: try: