Skip to content

Commit 9091fee

Browse files
committed
claims_challenge
1 parent 47d26b5 commit 9091fee

File tree

6 files changed

+33
-6
lines changed

6 files changed

+33
-6
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ def login(self,
152152
allow_no_subscriptions=False,
153153
use_cert_sn_issuer=None,
154154
show_progress=False,
155+
claims_challenge=None,
155156
**kwargs):
156157
"""
157158
For service principal, `password` is a dict returned by ServicePrincipalAuth.build_credential
@@ -174,7 +175,7 @@ def login(self,
174175
if use_device_code:
175176
user_identity = identity.login_with_device_code(scopes=scopes, **kwargs)
176177
else:
177-
user_identity = identity.login_with_auth_code(scopes=scopes, **kwargs)
178+
user_identity = identity.login_with_auth_code(scopes=scopes, claims_challenge=claims_challenge, **kwargs)
178179
else:
179180
if not is_service_principal:
180181
user_identity = identity.login_with_username_password(username, password, scopes=scopes, **kwargs)

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

Lines changed: 2 additions & 1 deletion
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, **kwargs):
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,6 +168,7 @@ 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+
claims_challenge=claims_challenge,
171172
**kwargs)
172173
return check_result(result)
173174

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,14 @@ def _generate_login_command(scopes=None, claims_challenge=None):
5858

5959
# Rejected by Conditional Access policy, like MFA
6060
if scopes:
61-
login_command.append('--scope {}'.format(' '.join(scopes)))
61+
# *scopes unpacks the list: https://peps.python.org/pep-0448/:
62+
login_command.extend(['--scope', *scopes])
6263

6364
# Rejected by CAE
6465
if claims_challenge:
66+
from azure.cli.core.util import b64encode
67+
claims_challenge_encoded = b64encode(claims_challenge)
68+
login_command.extend(['--claims', claims_challenge_encoded])
6569
# Explicit logout is needed: https://github.com/AzureAD/microsoft-authentication-library-for-python/issues/335
6670
return 'az logout\n' + ' '.join(login_command)
6771

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)