Skip to content

Commit ba47ebe

Browse files
committed
broker sso
1 parent 2d05a0e commit ba47ebe

5 files changed

Lines changed: 43 additions & 5 deletions

File tree

src/azure-cli-core/azure/cli/core/_profile.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ def login(self,
148148
is_service_principal,
149149
tenant,
150150
scopes=None,
151+
use_broker_sso=False,
151152
use_device_code=False,
152153
allow_no_subscriptions=False,
153154
use_cert_sn_issuer=None,
@@ -176,7 +177,10 @@ def login(self,
176177
if use_device_code:
177178
user_identity = identity.login_with_device_code(scopes=scopes, claims_challenge=claims_challenge)
178179
else:
179-
user_identity = identity.login_with_auth_code(scopes=scopes, claims_challenge=claims_challenge)
180+
user_identity = identity.login_with_auth_code(
181+
scopes=scopes,
182+
claims_challenge=claims_challenge,
183+
use_broker_sso=use_broker_sso)
180184
else:
181185
if not is_service_principal:
182186
user_identity = identity.login_with_username_password(username, password, scopes=scopes)

src/azure-cli-core/azure/cli/core/auth/agentic_session.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
COPILOT_AGENT_SESSION_ID = "COPILOT_AGENT_SESSION_ID"
2727

2828

29+
def is_agentic_session():
30+
"""Determine if we're in an agentic session based on the presence of COPILOT_AGENT_SESSION_ID."""
31+
return os.environ.get(COPILOT_AGENT_SESSION_ID) is not None
32+
33+
2934
def build_agentic_session_params():
3035
"""Read COPILOT_AGENT_SESSION_ID and build the agentic claims challenge.
3136

src/azure-cli-core/azure/cli/core/auth/identity.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Licensed under the MIT License. See License.txt in the project root for license information.
44
# --------------------------------------------------------------------------------------------
55

6+
import cmd
67
import json
78
import os
89
import re
@@ -145,7 +146,7 @@ def _service_principal_store(self):
145146
Identity._service_principal_store_instance = ServicePrincipalStore(store)
146147
return Identity._service_principal_store_instance
147148

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

@@ -161,15 +162,31 @@ def _prompt_launching_ui(ui=None, **_):
161162
from .util import read_response_templates
162163
success_template, error_template = read_response_templates()
163164

165+
from .agentic_session import is_agentic_session
166+
is_agentic_session_value = is_agentic_session()
167+
enable_broker_on_windows = cmd.cli_ctx.config.getboolean('core', 'enable_broker_on_windows', fallback=True)
168+
# Broker is available only on Windows for now
169+
broker_sso_available = sys.platform.startswith('win') and enable_broker_on_windows
170+
logger.debug("use_broker_sso: %s, is_agentic_session: %s, broker_sso_available: %s",
171+
use_broker_sso, is_agentic_session_value, broker_sso_available)
172+
use_broker_sso = (use_broker_sso or is_agentic_session_value) and broker_sso_available
173+
prompt = 'none' if use_broker_sso else 'select_account'
174+
164175
# For AAD, use port 0 to let the system choose arbitrary unused ephemeral port to avoid port collision
165176
# on port 8400 from the old design. However, ADFS only allows port 8400.
166177
result = self._msal_app.acquire_token_interactive(
167-
scopes, prompt='select_account', port=8400 if self._is_adfs else None,
178+
scopes,
179+
prompt=prompt,
180+
port=8400 if self._is_adfs else None,
168181
success_template=success_template, error_template=error_template,
169182
parent_window_handle=self._msal_app.CONSOLE_WINDOW_HANDLE, on_before_launching_ui=_prompt_launching_ui,
170183
enable_msa_passthrough=True,
171184
claims_challenge=claims_challenge)
172-
return check_result(result)
185+
parsed = check_result(result)
186+
if use_broker_sso:
187+
# log parsed result in debug level
188+
logger.debug("Result from broker SSO login: %s", json.dumps(parsed, indent=4))
189+
return parsed
173190

174191
def login_with_device_code(self, scopes, claims_challenge=None):
175192
flow = self._msal_app.initiate_device_flow(scopes, claims_challenge=claims_challenge)

src/azure-cli/azure/cli/command_modules/profile/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ def load_arguments(self, command):
5858
c.argument('claims_challenge',
5959
help="Base64-encoded claims challenge requested by a resource API in the "
6060
"WWW-Authenticate header.")
61+
c.argument('use_broker_sso', action='store_true',
62+
help="(Experimental) Enable broker SSO for login.")
6163
c.ignore('_subscription') # hide the global subscription parameter
6264

6365
# Skip subscription discovery

src/azure-cli/azure/cli/command_modules/profile/custom.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def _select_and_set_active(profile, subscriptions):
134134

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

173182
if claims_challenge:
174183
from azure.cli.core.util import b64decode
@@ -219,6 +228,7 @@ def login(cmd, username=None, password=None, tenant=None, scopes=None, allow_no_
219228
service_principal,
220229
tenant,
221230
scopes=scopes,
231+
use_broker_sso=use_broker_sso,
222232
use_device_code=use_device_code,
223233
allow_no_subscriptions=allow_no_subscriptions,
224234
use_cert_sn_issuer=use_cert_sn_issuer,

0 commit comments

Comments
 (0)