Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/azure-cli-core/azure/cli/core/auth/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
</style>
</head>
<body>
<h3>You have logged into Microsoft Azure!</h3>
<p>You can close this window, or we will redirect you to the <a href="https://learn.microsoft.com/cli/azure/">Azure CLI documentation</a> in 1 minute.</p>
{{wam_prompt}}
</body>
</html>
19 changes: 18 additions & 1 deletion src/azure-cli-core/azure/cli/core/auth/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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()
28 changes: 26 additions & 2 deletions src/azure-cli-core/azure/cli/core/auth/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = (
'<div class="wam-prompt">\n'
' <p>🔐 To better protect your account, we recommend enabling '
'<strong>Web Account Manager (WAM)</strong> &mdash; the Windows authentication broker. '
'It adds token protection, Windows Hello, conditional access, and streamlined single sign-on.</p>\n'
' <p>Enable it in a few steps: '
f'<a href="{WAM_ENABLEMENT_URL}">Sign in with Web Account Manager (WAM) on Windows</a>.</p>\n'
' </div>')


def aad_error_handler(error, tenant=None, scopes=None, claims_challenge=None):
""" Handle the error from AAD server returned by ADAL or MSAL. """

Expand Down Expand Up @@ -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()
Expand Down
Loading