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/_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ def login(self,
is_service_principal,
tenant,
scopes=None,
use_broker_sso=False,
use_device_code=False,
allow_no_subscriptions=False,
use_cert_sn_issuer=None,
Expand Down Expand Up @@ -176,7 +177,10 @@ def login(self,
if use_device_code:
user_identity = identity.login_with_device_code(scopes=scopes, claims_challenge=claims_challenge)
else:
user_identity = identity.login_with_auth_code(scopes=scopes, claims_challenge=claims_challenge)
user_identity = identity.login_with_auth_code(
scopes=scopes,
claims_challenge=claims_challenge,
use_broker_sso=use_broker_sso)
else:
if not is_service_principal:
user_identity = identity.login_with_username_password(username, password, scopes=scopes)
Expand Down
20 changes: 17 additions & 3 deletions src/azure-cli-core/azure/cli/core/auth/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def _service_principal_store(self):
Identity._service_principal_store_instance = ServicePrincipalStore(store)
return Identity._service_principal_store_instance

def login_with_auth_code(self, scopes, claims_challenge=None):
def login_with_auth_code(self, scopes, claims_challenge=None, use_broker_sso=False):
# Emit a warning to inform that a browser is opened.
# Only show the path part of the URL and hide the query string.

Expand All @@ -164,12 +164,18 @@ def _prompt_launching_ui(ui=None, **_):
# 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.
result = self._msal_app.acquire_token_interactive(
scopes, prompt='select_account', port=8400 if self._is_adfs else None,
scopes,
prompt='none' if use_broker_sso else 'select_account',
port=8400 if self._is_adfs else None,
success_template=success_template, error_template=error_template,
parent_window_handle=self._msal_app.CONSOLE_WINDOW_HANDLE, on_before_launching_ui=_prompt_launching_ui,
enable_msa_passthrough=True,
claims_challenge=claims_challenge)
return check_result(result)
parsed = check_result(result)
if use_broker_sso:
# log parsed result in debug level
logger.debug("Result from broker SSO login: %s", json.dumps(parsed, indent=4))
return parsed

def login_with_device_code(self, scopes, claims_challenge=None):
flow = self._msal_app.initiate_device_flow(scopes, claims_challenge=claims_challenge)
Expand Down Expand Up @@ -244,6 +250,14 @@ def get_service_principal_credential(self, client_id):
client_credential = ServicePrincipalAuth(entry).get_msal_client_credential()
return ServicePrincipalCredential(client_id, client_credential, **self._msal_app_kwargs)

# checks are now done in custom.py
# def _is_broker_sso(self):
# """Detect if SSO with broker is possible.
# It is only possible if broker is available (Windows for now) and enabled via config,
# AND user has opted in with the flag.
# """
# return self._enable_broker_on_windows and sys.platform.startswith('win') and self._broker_sso


class ServicePrincipalAuth: # pylint: disable=too-many-instance-attributes
def __init__(self, entry):
Expand Down
2 changes: 2 additions & 0 deletions src/azure-cli/azure/cli/command_modules/profile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ def load_arguments(self, command):
c.argument('claims_challenge',
help="Base64-encoded claims challenge requested by a resource API in the "
"WWW-Authenticate header.")
c.argument('use_broker_sso', action='store_true',
help="(TBD) Enable broker SSO for login.")
c.ignore('_subscription') # hide the global subscription parameter

# Skip subscription discovery
Expand Down
12 changes: 11 additions & 1 deletion src/azure-cli/azure/cli/command_modules/profile/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def _select_and_set_active(profile, subscriptions):

# pylint: disable=too-many-branches, too-many-locals
def login(cmd, username=None, password=None, tenant=None, scopes=None, allow_no_subscriptions=False,
claims_challenge=None,
claims_challenge=None, use_broker_sso=False,
# Device code flow
use_device_code=False,
# Service principal
Expand Down Expand Up @@ -169,6 +169,15 @@ def login(cmd, username=None, password=None, tenant=None, scopes=None, allow_no_
logger.warning(USERNAME_PASSWORD_DEPRECATION_WARNING_AZURE_CLOUD)
else:
logger.warning(USERNAME_PASSWORD_DEPRECATION_WARNING_OTHER_CLOUD)
# todo: broker_sso incompatible with workload identities
# broker_sso relies on the presence of a broker, which is only available on Windows (for now)
enable_broker_on_windows = cmd.cli_ctx.config.getboolean('core', 'enable_broker_on_windows', fallback=True)
broker_sso_available = sys.platform.startswith('win') and enable_broker_on_windows
if use_broker_sso and not broker_sso_available:
raise CLIError("usage error: '--use-broker-sso' is only supported on Windows with broker enabled")
if use_broker_sso and (service_principal or identity):
raise CLIError("usage error: '--use-broker-sso' is not applicable "
"to service principal or managed identity login")

if claims_challenge:
from azure.cli.core.util import b64decode
Expand Down Expand Up @@ -219,6 +228,7 @@ def login(cmd, username=None, password=None, tenant=None, scopes=None, allow_no_
service_principal,
tenant,
scopes=scopes,
use_broker_sso=use_broker_sso,
use_device_code=use_device_code,
allow_no_subscriptions=allow_no_subscriptions,
use_cert_sn_issuer=use_cert_sn_issuer,
Expand Down
Loading