Skip to content

Commit 02809f3

Browse files
authored
[Profile] az login: Support --claims-challenge in auth code flow (#31778)
1 parent a7e596e commit 02809f3

5 files changed

Lines changed: 35 additions & 14 deletions

File tree

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def login(self,
152152
allow_no_subscriptions=False,
153153
use_cert_sn_issuer=None,
154154
show_progress=False,
155-
**kwargs):
155+
claims_challenge=None):
156156
"""
157157
For service principal, `password` is a dict returned by ServicePrincipalAuth.build_credential
158158
"""
@@ -172,12 +172,12 @@ def login(self,
172172
use_device_code = True
173173

174174
if use_device_code:
175-
user_identity = identity.login_with_device_code(scopes=scopes, **kwargs)
175+
user_identity = identity.login_with_device_code(scopes=scopes)
176176
else:
177-
user_identity = identity.login_with_auth_code(scopes=scopes, **kwargs)
177+
user_identity = identity.login_with_auth_code(scopes=scopes, claims_challenge=claims_challenge)
178178
else:
179179
if not is_service_principal:
180-
user_identity = identity.login_with_username_password(username, password, scopes=scopes, **kwargs)
180+
user_identity = identity.login_with_username_password(username, password, scopes=scopes)
181181
else:
182182
identity.login_with_service_principal(username, password, scopes=scopes)
183183

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def _service_principal_store(self):
145145
Identity._service_principal_store_instance = ServicePrincipalStore(store)
146146
return Identity._service_principal_store_instance
147147

148-
def login_with_auth_code(self, scopes, **kwargs):
148+
def login_with_auth_code(self, scopes, claims_challenge=None):
149149
# Emit a warning to inform that a browser is opened.
150150
# Only show the path part of the URL and hide the query string.
151151

@@ -168,21 +168,21 @@ def _prompt_launching_ui(ui=None, **_):
168168
success_template=success_template, error_template=error_template,
169169
parent_window_handle=self._msal_app.CONSOLE_WINDOW_HANDLE, on_before_launching_ui=_prompt_launching_ui,
170170
enable_msa_passthrough=True,
171-
**kwargs)
171+
claims_challenge=claims_challenge)
172172
return check_result(result)
173173

174-
def login_with_device_code(self, scopes, **kwargs):
175-
flow = self._msal_app.initiate_device_flow(scopes, **kwargs)
174+
def login_with_device_code(self, scopes):
175+
flow = self._msal_app.initiate_device_flow(scopes)
176176
if "user_code" not in flow:
177177
raise ValueError(
178178
"Fail to create device flow. Err: %s" % json.dumps(flow, indent=4))
179179
from azure.cli.core.style import print_styled_text, Style
180180
print_styled_text((Style.WARNING, flow["message"]), file=sys.stderr)
181-
result = self._msal_app.acquire_token_by_device_flow(flow, **kwargs) # By default it will block
181+
result = self._msal_app.acquire_token_by_device_flow(flow) # By default it will block
182182
return check_result(result)
183183

184-
def login_with_username_password(self, username, password, scopes, **kwargs):
185-
result = self._msal_app.acquire_token_by_username_password(username, password, scopes, **kwargs)
184+
def login_with_username_password(self, username, password, scopes):
185+
result = self._msal_app.acquire_token_by_username_password(username, password, scopes)
186186
return check_result(result)
187187

188188
def login_with_service_principal(self, client_id, credential, scopes):

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,13 +603,24 @@ def shell_safe_json_parse(json_or_dict_string, preserve_order=False, strict=True
603603

604604
def b64encode(s):
605605
"""
606-
Encodes a string to base64 on 2.x and 3.x
606+
Encodes a string to a base64 string.
607607
:param str s: latin_1 encoded string
608608
:return: base64 encoded string
609609
:rtype: str
610610
"""
611611
encoded = base64.b64encode(s.encode("latin-1"))
612-
return encoded if encoded is str else encoded.decode('latin-1')
612+
return encoded.decode('latin-1')
613+
614+
615+
def b64decode(s):
616+
"""
617+
Decodes a base64 string to a string.
618+
:param str s: latin_1 encoded base64 string
619+
:return: decoded string
620+
:rtype: str
621+
"""
622+
encoded = base64.b64decode(s.encode("latin-1"))
623+
return encoded.decode('latin-1')
613624

614625

615626
def b64_to_hex(s):

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ def load_arguments(self, command):
5555
c.argument('allow_no_subscriptions', action='store_true',
5656
help="Support accessing tenants without subscriptions. It's useful to run "
5757
"tenant-level commands, such as 'az ad'.")
58+
c.argument('claims_challenge',
59+
help="Base64-encoded claims challenge requested by a resource API in the "
60+
"WWW-Authenticate header.")
5861
c.ignore('_subscription') # hide the global subscription parameter
5962

6063
# Device code flow

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ def account_clear(cmd):
122122

123123
# pylint: disable=too-many-branches, too-many-locals
124124
def login(cmd, username=None, password=None, tenant=None, scopes=None, allow_no_subscriptions=False,
125+
claims_challenge=None,
125126
# Device code flow
126127
use_device_code=False,
127128
# Service principal
@@ -148,6 +149,10 @@ def login(cmd, username=None, password=None, tenant=None, scopes=None, allow_no_
148149
else:
149150
logger.warning(USERNAME_PASSWORD_DEPRECATION_WARNING_OTHER_CLOUD)
150151

152+
if claims_challenge:
153+
from azure.cli.core.util import b64decode
154+
claims_challenge = b64decode(claims_challenge)
155+
151156
interactive = False
152157

153158
profile = Profile(cli_ctx=cmd.cli_ctx)
@@ -194,7 +199,9 @@ def login(cmd, username=None, password=None, tenant=None, scopes=None, allow_no_
194199
use_device_code=use_device_code,
195200
allow_no_subscriptions=allow_no_subscriptions,
196201
use_cert_sn_issuer=use_cert_sn_issuer,
197-
show_progress=select_subscription)
202+
show_progress=select_subscription,
203+
claims_challenge=claims_challenge
204+
)
198205

199206
# Launch interactive account selection. No JSON output.
200207
if select_subscription:

0 commit comments

Comments
 (0)