Skip to content

Commit 5c3cf2f

Browse files
authored
{Auth} Add --claims-challenge to the re-authentication message (#31699)
1 parent 0d65ac1 commit 5c3cf2f

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ def acquire_token(self, scopes, claims_challenge=None, **kwargs):
5151
scopes, claims_challenge, kwargs)
5252

5353
if claims_challenge:
54-
logger.warning('Acquiring new access token silently for tenant %s with claims challenge: %s',
55-
self._msal_app.authority.tenant, claims_challenge)
54+
logger.info('Acquiring new access token silently with claims challenge: %s', claims_challenge)
5655
result = self._msal_app.acquire_token_silent_with_error(
5756
scopes, self._account, claims_challenge=claims_challenge, **kwargs)
5857

src/azure-cli-core/azure/cli/core/auth/tests/test_util.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ def test_generate_login_command(self):
6868
assert actual == ('az login --tenant "21987a97-4e85-47c5-9a13-9dc3e11b2a9a" '
6969
'--scope "https://management.core.windows.net//.default"')
7070

71+
# tenant, scopes and claims_challenge
72+
actual = _generate_login_command(
73+
tenant='21987a97-4e85-47c5-9a13-9dc3e11b2a9a',
74+
scopes=["https://management.core.windows.net//.default"],
75+
claims_challenge='{"access_token":{"acrs":{"essential":true,"values":["p1"]}}}')
76+
assert actual == ('az logout\n'
77+
'az login --tenant "21987a97-4e85-47c5-9a13-9dc3e11b2a9a" '
78+
'--scope "https://management.core.windows.net//.default" '
79+
'--claims-challenge "eyJhY2Nlc3NfdG9rZW4iOnsiYWNycyI6eyJlc3NlbnRpYWwiOnRydWUsInZhbHVlcyI6WyJwMSJdfX19"')
7180

7281

7382
if __name__ == '__main__':

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

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"To pass a service principal certificate, use --certificate instead.")
2121

2222

23-
def aad_error_handler(error, **kwargs):
23+
def aad_error_handler(error, tenant=None, scopes=None, claims_challenge=None):
2424
""" Handle the error from AAD server returned by ADAL or MSAL. """
2525

2626
# https://learn.microsoft.com/en-us/azure/active-directory/develop/reference-aadsts-error-codes
@@ -41,11 +41,21 @@ def aad_error_handler(error, **kwargs):
4141
error_codes = error.get('error_codes')
4242

4343
# Build recommendation message
44+
recommendation = None
4445
if error_codes and 7000215 in error_codes:
4546
recommendation = PASSWORD_CERTIFICATE_WARNING
4647
else:
47-
login_command = _generate_login_command(**kwargs)
48-
recommendation = "Interactive authentication is needed. Please run:\n{}".format(login_command)
48+
login_command = _generate_login_command(tenant=tenant, scopes=scopes, claims_challenge=claims_challenge)
49+
login_message = ('Run the command below to authenticate interactively; '
50+
'additional arguments may be added as needed:\n'
51+
f'{login_command}')
52+
53+
# During a challenge, the exception will caught by azure-mgmt-core, so we show a warning now
54+
if claims_challenge:
55+
logger.info('Failed to acquire token silently. Error detail: %s', error_description)
56+
logger.warning(login_message)
57+
else:
58+
recommendation = login_message
4959

5060
from azure.cli.core.azclierror import AuthenticationError
5161
raise AuthenticationError(error_description, msal_error=error, recommendation=recommendation)
@@ -69,10 +79,14 @@ def _generate_login_command(tenant=None, scopes=None, claims_challenge=None):
6979

7080
# Rejected by CAE
7181
if claims_challenge:
72-
# Explicit logout is needed: https://github.com/AzureAD/microsoft-authentication-library-for-python/issues/335
73-
return 'az logout\n' + ' '.join(login_command)
82+
from azure.cli.core.util import b64encode
83+
# Base64 encode the claims_challenge to avoid shell interpretation
84+
claims_challenge_encoded = b64encode(claims_challenge)
85+
login_command.extend(['--claims-challenge', f'"{claims_challenge_encoded}"'])
7486

75-
return ' '.join(login_command)
87+
# Explicit logout is preferred, making sure MSAL cache is purged:
88+
# https://github.com/AzureAD/microsoft-authentication-library-for-python/issues/335
89+
return 'az logout\n' + ' '.join(login_command)
7690

7791

7892
def resource_to_scopes(resource):
@@ -113,7 +127,7 @@ def scopes_to_resource(scopes):
113127
return scope
114128

115129

116-
def check_result(result, **kwargs):
130+
def check_result(result, tenant=None, scopes=None, claims_challenge=None):
117131
"""Parse the result returned by MSAL:
118132
119133
1. Check if the MSAL result contains a valid access token.
@@ -132,7 +146,7 @@ def check_result(result, **kwargs):
132146
set_msal_telemetry(result['msal_telemetry'])
133147

134148
if 'error' in result:
135-
aad_error_handler(result, **kwargs)
149+
aad_error_handler(result, tenant=tenant, scopes=scopes, claims_challenge=claims_challenge)
136150

137151
# For user authentication
138152
if 'id_token_claims' in result:

0 commit comments

Comments
 (0)