Skip to content

Conversation

@jiasli
Copy link
Member

@jiasli jiasli commented Apr 16, 2021

Resolve #15220
Require #17778 which resolves #17551

Context

When ARM doesn't require MFA, but data-plane service does, CLI fails and can't recover.

Change

When CLI fails because ARM's Refresh Token doesn't have permission to get data-plane service's Access Token (step-up), CLI gives an instruction to re-login with --scope:

AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to access 'ce6ff14a-7fdc-4685-bbe0-f6afdfcfa8e0'.
Trace ID: 9df367fc-f494-4cb4-8080-525b1a3d2800
Correlation ID: e1801d21-4173-4634-adcc-5c3f238bd9b2
Timestamp: 2021-04-16 12:34:57Z
To re-authenticate, please run:
az login --scope https://pas.windows.net/CheckMyAccess/Linux/.default
If the problem persists, please contact your tenant administrator.

Additional context

This is a non-automated solution to #17093, because we don't want CLI to launch a browser automatically during script execution.

Comment on lines 10 to 11
Copy link
Member Author

@jiasli jiasli Apr 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This _get_token never works because it doesn't comply with KeyVaultAuthentication's authorization_callback signature.

Copy link
Member Author

@jiasli jiasli Apr 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As pointed by #15854, calling the protected method _token_retriever is simply wrong.

Switch to calling azure.cli.command_modules.keyvault._client_factory.keyvault_data_plane_factory instead which calls the correct get_raw_token method provided by #15805 (comment).

Appconfig already adopted this approach in #15826.

Copy link
Member Author

@jiasli jiasli Apr 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To support being called as keyvault_data_plane_factory(cli_ctx).

@yonzhan yonzhan added this to the S186 milestone Apr 16, 2021
@yonzhan
Copy link
Collaborator

yonzhan commented Apr 16, 2021

Show --scope for az login message when failed to refresh the access token

Copy link
Collaborator

@yonzhan yonzhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@jiasli jiasli marked this pull request as ready for review April 20, 2021 06:42
@jiasli jiasli requested a review from kairu-ms as a code owner April 22, 2021 08:59
@yonzhan yonzhan modified the milestones: S186, S187 May 1, 2021
@yonzhan yonzhan modified the milestones: S187, S188 May 22, 2021
@yonzhan yonzhan modified the milestones: S188, S189 Jun 13, 2021
@yonzhan yonzhan modified the milestones: S189, Jul 2021 (2021-08-03) Jul 2, 2021
Comment on lines +217 to +218
def setUp(self):
patch_main_exception_handler(self)
Copy link
Member Author

@jiasli jiasli Aug 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

azure.cli.core.util.handle_exception is patched for ScenarioTest. We have to patch azure.cli.core.util.handle_exception for LiveScenarioTest as well. Otherwise, AuthenticationError can't be checked in tests.

@jiasli jiasli changed the title [Core] Conditional Access: Show --scope for az login message [Core] Conditional Access: Show --scope for az login message when failed to refresh the access token Aug 17, 2021
@jiasli
Copy link
Member Author

jiasli commented Mar 10, 2023

Some more information I provided in an internal ticket:

Why token refreshing fails

Consider the following scenario:

  1. ARM doesn't require MFA
  2. But data-plane services (like MS Graph, Storage) do, which is enforced by Conditional Access policy

Without --scope provided, az login by default authenticates against ARM https://management.core.windows.net//.default. So az login is equivalent to

az login --scope https://management.core.windows.net//.default

If ARM doesn’t have Conditional Access policies enforced, the refresh token won’t be compliant with MS Graph’s Conditional Access policy. However, when the user (possibly through Terraform) requests an access token for MS Graph (step-up refreshing) with

az account get-access-token --scope https://graph.microsoft.com//.default

the token refreshing request will fail. That’s exactly why the error message is introduced in this PR to instruct the user to re-authenticate interactively.

Best practice for using Azure CLI non-interactively

The best practice for using Azure CLI (or through Terraform) without any interaction after az login is to make az login authenticate against the scope that has the most strict Conditional Access policy enforced, e.g., MS Graph:

az login --scope https://graph.microsoft.com//.default

Then the step-down refreshing (MS Graph -> ARM) is silent.

2 possible scenarios

However, there are 2 scenarios we have considered but haven’t solved yet (luckily, haven’t encountered either):

  1. What if ARM and MS Graph have non-overlapping sets of Conditional Access policies enforced? In other words, the refresh token for ARM can’t be used to get access tokens for MS Graph and vice versa.
  2. On top of that, we can extend this to cross-tenant scenarios - what if different tenants have non-overlapping sets of Conditional Access policies enforced. Then the refresh token can’t be used to do cross-tenant refreshing either.

Providing 2 scopes at the same time? Unfortunately, this doesn't work because only one static resource can be provided:

> az account get-access-token --scope https://management.core.windows.net//.default https://graph.microsoft.com//.default
AADSTS70011: The provided request must include a 'scope' input parameter. The provided value for the input parameter
'scope' is not valid. The scope https://graph.microsoft.com//.default https://management.core.windows.net//.default
offline_access openid profile is not valid. static scope limit exceeded.
...

Previously we had some discussion on this topic with MSAL team @rayluo. This can fundamentally affect how MSAL’s token refreshing mechanism works, as this would require MSAL to bind refresh tokens to different scopes and tenants as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Support --scope in az login Support Conditional Access

5 participants