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
4 changes: 2 additions & 2 deletions src/azure-cli-core/azure/cli/core/_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ def get_login_credentials(self, resource=None, subscription_id=None, aux_subscri
str(account[_SUBSCRIPTION_ID]),
str(account[_TENANT_ID]))

def get_raw_token(self, resource=None, scopes=None, subscription=None, tenant=None):
def get_raw_token(self, resource=None, scopes=None, subscription=None, tenant=None, client_id=None):
# Convert resource to scopes
if resource and not scopes:
from .auth.util import resource_to_scopes
Expand Down Expand Up @@ -458,7 +458,7 @@ def get_raw_token(self, resource=None, scopes=None, subscription=None, tenant=No
scopes_to_resource(scopes))

else:
cred = self._create_credential(account, tenant_id=tenant)
cred = self._create_credential(account, tenant_id=tenant, client_id=client_id)

sdk_token = cred.get_token(*scopes)
# Convert epoch int 'expires_on' to datetime string 'expiresOn' for backward compatibility
Expand Down
1 change: 1 addition & 0 deletions src/azure-cli-core/azure/cli/core/auth/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def __init__(self, authority, tenant_id=None, client_id=None, encrypt=False, use
"""
self.authority = authority
self.tenant_id = tenant_id
# This client ID is only used for PublicClientApplication, not ConfidentialClientApplication
self.client_id = client_id or AZURE_CLI_CLIENT_ID
self._encrypt = encrypt
self._use_msal_http_cache = use_msal_http_cache
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 @@ -101,6 +101,8 @@ def load_arguments(self, command):
c.argument('tenant', options_list=['--tenant', '-t'],
help='Tenant ID for which the token is acquired. Only available for user and service principal '
'account, not for managed identity or Cloud Shell account')
c.argument('client_id',
help='A first-party app ID that can do single sign-on with Azure CLI.')


COMMAND_LOADER_CLS = ProfileCommandsLoader
7 changes: 4 additions & 3 deletions src/azure-cli/azure/cli/command_modules/profile/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ def show_subscription(cmd, subscription=None):
return profile.get_subscription(subscription)


def get_access_token(cmd, subscription=None, resource=None, scopes=None, resource_type=None, tenant=None):
def get_access_token(cmd, subscription=None, resource=None, scopes=None, resource_type=None, tenant=None,
client_id=None):
"""
get AAD token to access to a specified resource.
Use 'az cloud show' command for other Azure resources
Expand All @@ -80,8 +81,8 @@ def get_access_token(cmd, subscription=None, resource=None, scopes=None, resourc
resource = getattr(cmd.cli_ctx.cloud.endpoints, endpoints_attr_name)

profile = Profile(cli_ctx=cmd.cli_ctx)
creds, subscription, tenant = profile.get_raw_token(subscription=subscription, resource=resource, scopes=scopes,
tenant=tenant)
creds, subscription, tenant = profile.get_raw_token(
subscription=subscription, resource=resource, scopes=scopes, tenant=tenant, client_id=client_id)

result = {
'tokenType': creds[0],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ def test_get_raw_token(self, get_raw_token_mock):
result = get_access_token(cmd)

# assert
get_raw_token_mock.assert_called_with(mock.ANY, None, None, None, None)
get_raw_token_mock.assert_called_with(mock.ANY, resource=None, scopes=None, subscription=None, tenant=None,
client_id=None)
expected_result = {
'tokenType': 'bearer',
'accessToken': 'token123',
Expand All @@ -66,12 +67,13 @@ def test_get_raw_token(self, get_raw_token_mock):
subscription_id = '00000001-0000-0000-0000-000000000000'
get_raw_token_mock.return_value = (('bearer', 'token123', token_entry), subscription_id, 'tenant123')
result = get_access_token(cmd, subscription=subscription_id, resource=resource)
get_raw_token_mock.assert_called_with(mock.ANY, resource, None, subscription_id, None)
get_raw_token_mock.assert_called_with(mock.ANY, resource=resource, scopes=None, subscription=subscription_id,
tenant=None, client_id=None)

# assert it takes customized scopes
get_access_token(cmd, scopes='https://graph.microsoft.com/.default')
get_raw_token_mock.assert_called_with(mock.ANY, None, scopes='https://graph.microsoft.com/.default',
subscription=None, tenant=None)
get_raw_token_mock.assert_called_with(mock.ANY, resource=None, scopes='https://graph.microsoft.com/.default',
subscription=None, tenant=None, client_id=None)

# test get token with tenant
tenant_id = '00000000-0000-0000-0000-000000000000'
Expand All @@ -85,7 +87,8 @@ def test_get_raw_token(self, get_raw_token_mock):
'tenant': tenant_id
}
self.assertEqual(result, expected_result)
get_raw_token_mock.assert_called_with(mock.ANY, None, None, None, tenant_id)
get_raw_token_mock.assert_called_with(mock.ANY, resource=None, scopes=None, subscription=None,
tenant=tenant_id, client_id=None)

@mock.patch('azure.cli.command_modules.profile.custom.Profile', autospec=True)
def test_get_login(self, profile_mock):
Expand Down
Loading