Azure-sdk-for-net: DefaultAzureCredential does not use az cli login

Created on 27 Nov 2019  路  17Comments  路  Source: Azure/azure-sdk-for-net

In the old APIs we had AzureServiceTokenProvider to log in with Managed Identity. If you were running locally and had logged in with the az cli, AzureServiceTokenProvider would simply use your az session.
This code worked locally, as long as you were logged in with az cli in the old APIs:

var tokenProvider = new AzureServiceTokenProvider();
keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(tokenProvider.KeyVaultTokenCallback));
var secretValue = keyVaultClient.GetSecretAsync(keyVaultUrl, supersecretname).Result;

However, this does not work with the new APIs. For example, this code:

var client = new SecretClient(vaultUri: new Uri(keyVaultUrl), credential: new DefaultAzureCredential());
var secretValue = client.GetSecret(supersecretname);

throws this exception:

Exception has occurred: CLR/Azure.Identity.AuthenticationFailedException
An unhandled exception of type 'Azure.Identity.AuthenticationFailedException' occurred in Azure.Security.KeyVault.Secrets.dll: 'The DefaultAzureCredential failed to retrieve a token from the included credentials.
  EnvironmentCredential is unavailable Environment variables not fully configured. AZURE_TENANT_ID and AZURE_CLIENT_ID must be set, along with either AZURE_CLIENT_SECRET or AZURE_USERNAME and AZURE_PASSWORD. Currently set variables [  ].
  ManagedIdentityCredential is unavailable No managed identity endpoint found..
  SharedTokenCacheCredential is unavailable Token acquisition failed for user . To fix, re-authenticate through developer tooling supporting Azure single sign on..
Azure.Identity Client

Most helpful comment

@sm15455 Sorry, for the delay in information. We are actively working on this and hope to have a preview which enables using the azure cli login for authentication in Azure.Identity sometime in March.

All 17 comments

FYI - We are discussing this internally and should have news in January.

Any updates on this issue?
The new library offers a development experience that is worse compared to the old one. With the new library I'm forced to create environment variables on my machine, with the old one I just have to login uzing AZ CLI.

@sm15455 Sorry, for the delay in information. We are actively working on this and hope to have a preview which enables using the azure cli login for authentication in Azure.Identity sometime in March.

As a work-around, I created a token credential class that uses AzureServiceTokenProvider:

    public class AzureServiceTokenCredential : TokenCredential
    {
        public AzureServiceTokenCredential(string endPoint)
        {
            if (string.IsNullOrWhiteSpace(endPoint))
            {
                throw new ArgumentException("message", nameof(endPoint));
            }

            EndPoint = endPoint;
        }

        public string EndPoint { get; }

        public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }

        public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            var tokenProvider = new AzureServiceTokenProvider();
            return new ValueTask<AccessToken>(tokenProvider
                .GetAccessTokenAsync(EndPoint, null, cancellationToken)
                .ContinueWith(task => {
                    return new AccessToken(task.Result, DateTimeOffset.MaxValue);
                }));
        }
    }

Then I can use this credential for other Azure services:

var blobAccountUri = new Uri(Config.StorageUrl);
var identity = new AzureServiceTokenCredential(Config.StorageUrl);
var blobClient = new BlobServiceClient(blobAccountUri, identity);

Maybe there is a better solution, but this works for me.

@flytzen Today we released a Azure.Identity 1.2.0-preview.1 which contains updates to the DefaultAzureCredential to use the Azure CLI logged in account when available. Please try out this new functionality and let us know if you have any questions or feedback.

Keep in mind that this feature is in preview, so some of the details like configuration are subject to change. This is the first of several previews we intend to ship with enhancements to the development time experience of the Azure.Identity library, with the ultimate goal of releasing them as GA sometime this summer.

This seems to work now for me, for the latest az cli .. but any further news on when this will work properly with Visual Studio 2017/2019?

@logiclabs I have not confirmed this works. A colleague sent it to me. I am no longer badly affected by this problem. I do encounter some annoying credential validation checks this might fix.
https://www.rahulpnath.com/blog/defaultazurecredential_from_azure_sdk/

This works with "Azure.Identity" Version="1.2.0-preview.1".
@schaabs Any ETA on GA for this package ?

cc : @satyamP04

FWIW this is still not fixed in Python azure-identity PyPI package v1.3.1

Hi team,
1.2.0-preview.3 broke the Az login authorization again.
1.2.0-preview.1 works.
Also, you would expect that if your Visual Studio 2019 dev account fail to authorize. It will pick as next option - the az CLI. But this is not the case. It fails if the tenant/subscription is incorrect with hard error: "The access token is from the wrong issuer..." and so on.
So, know if I want to use the CLI as a workaround to authorize Azure App Configuration, I have to explicitly sign out from VS.
Btw, With the latest VS 2019, you can't change the "Default Azure Active Directory" option in Account settings. Using the drop down or even if i do "az account set -s {sub}" and i see that "isDefault": true"

Ok, I found workaround. If you set ExcludeSharedTokenCacheCredential = true, this will skip your VS credentials and will go to CLI.
DefaultAzureCredentialOptions defaultAzureCredentialOptions = new DefaultAzureCredentialOptions { ExcludeSharedTokenCacheCredential = true }; var credentials = new DefaultAzureCredential(defaultAzureCredentialOptions);

However, we still need to figure out why we can't change the default tenant in VS Account Settings. There is "Apply filter" setting, after selecting the correct tenant, still get the "The access token is from the wrong issuer.."
Keep in mind that the older: AzureServiceTokenProvider works with our VS account. As soon as we start using the DefaultAzureCredential is not working anymore.
Maybe there was a change on how the VS credentials are used?

I just tried with Python azure-identity preview package 1.4.0b3 and things ALMOST work the way you would expect, but there's still a bug. The VSCodeCredential and AzureCliCredential picks up credentials from those locations if logged in there.

But if I log out of VSCode and az cli, and then do:

        credential = identity.DefaultAzureCredential(
            exclude_shared_token_cache_credential=False,
            exclude_visual_studio_code_credential=False,
            exclude_cli_credential=False,
            exclude_interactive_browser_credential=False
        )

I expect that, if the credential chain fails that it will eventually use the InteractiveBrowserCredential. Instead, it stops at AzureCliCredential. That's unfortunate, because ultimately I would like my tool to fall back to using the browser if nothing else is already logged in.

Here's the exception:

DefaultAzureCredential failed to retrieve a token from the included credentials.
Attempted credentials:
    EnvironmentCredential: EnvironmentCredential authentication unavailable. Environment variables are not fully configured.
    ManagedIdentityCredential: ManagedIdentityCredential authentication unavailable, no managed identity endpoint found.
    SharedTokenCacheCredential: SharedTokenCacheCredential authentication unavailable. No accounts were found in the cache.
    VSCodeCredential: No Azure user is logged in to Visual Studio Code.
    AzureCliCredential: Please run 'az login' to setup account.

I can see that InteractiveBrowserCredential is definitely part of the chain, and if I change to exclude_cli_credential=True, then the browser is launched as expected. So something's wrong with AzureCliCredential such that it interrupts the chain when it's included.

Following up: AzureCliCredential is indeed doing the wrong thing. When the CLI is not logged in, it is incorrectly raising ClientAuthenticationError when it should be raising CredentialUnavailableError. That causes the chain to stop instead of continuing on to the next. (At least, that's what it's doing in the Python 1.4.0b3 version.)

@mpderbec have you filed an issue against our python SDK? If not could you open an issue here.

Just to reiterate that while this worked in preview 1, 1.2.0-preview.3 broke the Az login authorization again.

@mpderbec have you filed an issue against our python SDK? If not could you open an issue here.

Done: https://github.com/Azure/azure-sdk-for-python/issues/11819

Thank you for the pointer @schaabs!

btw: I am able to do this today

az login --service-principal -u bd96aa5e-ff6a-4062-b514-c372053507b3 -p **REDACTED** --tenant **REDACTED**
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe"

I don't have to login anywhere in VS.
When debugging in VS everything works.

  AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
  var authCallback = new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback);
  var keyVaultClient = new KeyVaultClient(authCallback);
  var keyIdentifier = "test";
  var page = await keyVaultClient.GetKeyVersionsAsync(KeyVaultUrl, KeyIdentifier);

Can we make sure when we do fix this DefaultAzureCredential approach that it works under my use case.

i.e.
As a developer I would like VS to gain the az login context when launched via CMD.

Was this page helpful?
0 / 5 - 0 ratings