From 474a39d91e863ee4aeefdf20b9e04c8168ff8996 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Jul 2026 03:19:23 +0000 Subject: [PATCH 1/3] Initial plan From 544b8c7ff17e0158f3f04b225c7208744f47a17e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Jul 2026 03:24:21 +0000 Subject: [PATCH 2/3] Add WAM broker recommendation to browser login success page --- .../azure/cli/core/auth/identity.py | 6 +++- .../cli/core/auth/landing_pages/success.html | 9 ++++++ .../azure/cli/core/auth/tests/test_util.py | 19 ++++++++++++- .../azure/cli/core/auth/util.py | 28 +++++++++++++++++-- 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/azure-cli-core/azure/cli/core/auth/identity.py b/src/azure-cli-core/azure/cli/core/auth/identity.py index 91629e89441..dc4573d1c27 100644 --- a/src/azure-cli-core/azure/cli/core/auth/identity.py +++ b/src/azure-cli-core/azure/cli/core/auth/identity.py @@ -159,7 +159,11 @@ def _prompt_launching_ui(ui=None, **_): logger.warning(WAM_PROMPT) from .util import read_response_templates - success_template, error_template = read_response_templates() + # Recommend enabling the Windows broker (WAM) on the browser login success page only when + # the broker is disabled on a WAM-capable Windows platform, i.e. the user is falling back + # to browser-based login on Windows. + show_wam_prompt = sys.platform == 'win32' and not self._enable_broker_on_windows + success_template, error_template = read_response_templates(show_wam_prompt=show_wam_prompt) # For AAD, use port 0 to let the system choose arbitrary unused ephemeral port to avoid port collision # on port 8400 from the old design. However, ADFS only allows port 8400. diff --git a/src/azure-cli-core/azure/cli/core/auth/landing_pages/success.html b/src/azure-cli-core/azure/cli/core/auth/landing_pages/success.html index a4eb5069a79..323f0a49ef6 100644 --- a/src/azure-cli-core/azure/cli/core/auth/landing_pages/success.html +++ b/src/azure-cli-core/azure/cli/core/auth/landing_pages/success.html @@ -16,10 +16,19 @@ padding: 12px 16px; margin: 8px 0px; } + + .wam-prompt { + background-color: rgb(242, 242, 242); + border-left: 4px solid rgb(0, 120, 212); + padding: 12px 16px; + margin: 16px 0px; + max-width: 640px; + }

You have logged into Microsoft Azure!

You can close this window, or we will redirect you to the Azure CLI documentation in 1 minute.

+ {{wam_prompt}} diff --git a/src/azure-cli-core/azure/cli/core/auth/tests/test_util.py b/src/azure-cli-core/azure/cli/core/auth/tests/test_util.py index 0f1cab686c1..58c841c4056 100644 --- a/src/azure-cli-core/azure/cli/core/auth/tests/test_util.py +++ b/src/azure-cli-core/azure/cli/core/auth/tests/test_util.py @@ -6,7 +6,8 @@ # pylint: disable=protected-access import unittest -from azure.cli.core.auth.util import scopes_to_resource, resource_to_scopes, _generate_login_command +from azure.cli.core.auth.util import (scopes_to_resource, resource_to_scopes, _generate_login_command, + read_response_templates, WAM_ENABLEMENT_URL) class TestUtil(unittest.TestCase): @@ -78,6 +79,22 @@ def test_generate_login_command(self): '--scope "https://management.core.windows.net//.default" ' '--claims-challenge "eyJhY2Nlc3NfdG9rZW4iOnsiYWNycyI6eyJlc3NlbnRpYWwiOnRydWUsInZhbHVlcyI6WyJwMSJdfX19"') + def test_read_response_templates_without_wam_prompt(self): + # By default, the WAM prompt is not included and the placeholder is removed. + success_template, error_template = read_response_templates() + assert '{{wam_prompt}}' not in success_template + assert 'Web Account Manager (WAM)' not in success_template + assert WAM_ENABLEMENT_URL not in success_template + # error template is always returned + assert '$error' in error_template + + def test_read_response_templates_with_wam_prompt(self): + # When requested, the WAM prompt is injected with the enablement doc link. + success_template, _ = read_response_templates(show_wam_prompt=True) + assert '{{wam_prompt}}' not in success_template + assert 'Web Account Manager (WAM)' in success_template + assert WAM_ENABLEMENT_URL in success_template + if __name__ == '__main__': unittest.main() diff --git a/src/azure-cli-core/azure/cli/core/auth/util.py b/src/azure-cli-core/azure/cli/core/auth/util.py index 89ea054a32c..9057457365c 100644 --- a/src/azure-cli-core/azure/cli/core/auth/util.py +++ b/src/azure-cli-core/azure/cli/core/auth/util.py @@ -20,6 +20,23 @@ "To pass a service principal certificate, use --certificate instead.") +# WAM enablement doc for Azure CLI. +WAM_ENABLEMENT_URL = ( + "https://learn.microsoft.com/en-us/cli/azure/" + "authenticate-azure-cli-interactively#sign-in-with-web-account-manager-wam-on-windows") + +# HTML snippet injected into the browser login success page to recommend enabling the +# Windows broker (Web Account Manager, WAM). Injected by read_response_templates. +_WAM_PROMPT_HTML = ( + '
\n' + '

🔐 To better protect your account, we recommend enabling ' + 'Web Account Manager (WAM) — the Windows authentication broker. ' + 'It adds token protection, Windows Hello, conditional access, and streamlined single sign-on.

\n' + '

Enable it in a few steps: ' + 'Sign in with Web Account Manager (WAM) on Windows.

\n' + '
') + + def aad_error_handler(error, tenant=None, scopes=None, claims_challenge=None): """ Handle the error from AAD server returned by ADAL or MSAL. """ @@ -185,12 +202,19 @@ def decode_access_token(access_token): return json.loads(decoded_str) -def read_response_templates(): - """Read from success.html and error.html to strings and pass them to MSAL. """ +def read_response_templates(show_wam_prompt=False): + """Read from success.html and error.html to strings and pass them to MSAL. + + :param show_wam_prompt: Whether to include the prompt that recommends enabling the Windows + broker (Web Account Manager, WAM) in the success page. This should only be enabled for + browser-based login on a WAM-capable Windows platform where the broker is disabled. + """ success_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'landing_pages', 'success.html') with open(success_file) as f: success_template = f.read() + success_template = success_template.replace('{{wam_prompt}}', _WAM_PROMPT_HTML if show_wam_prompt else '') + error_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'landing_pages', 'error.html') with open(error_file) as f: error_template = f.read() From 7a173da3226bf0bb217fe21f8cee558351b94e26 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Jul 2026 03:25:03 +0000 Subject: [PATCH 3/3] Use f-string for WAM prompt HTML link --- src/azure-cli-core/azure/cli/core/auth/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli-core/azure/cli/core/auth/util.py b/src/azure-cli-core/azure/cli/core/auth/util.py index 9057457365c..7f584af87cb 100644 --- a/src/azure-cli-core/azure/cli/core/auth/util.py +++ b/src/azure-cli-core/azure/cli/core/auth/util.py @@ -33,7 +33,7 @@ 'Web Account Manager (WAM) — the Windows authentication broker. ' 'It adds token protection, Windows Hello, conditional access, and streamlined single sign-on.

\n' '

Enable it in a few steps: ' - 'Sign in with Web Account Manager (WAM) on Windows.

\n' + f'Sign in with Web Account Manager (WAM) on Windows.

\n' ' ')