question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Azure.Identity 1.4- SharedTokenCacheCredential no longer works when used in DefaultAzureCredentialOptions

See original GitHub issue

Library name and version

Azure.Identity 1.5

Describe the bug

Pardon the title gore.

This commit https://github.com/Azure/azure-sdk-for-net/commit/215a57637d0b115b4231c47b7df37452ff0772a2 changed how we hook up TokenCache:

https://github.com/Azure/azure-sdk-for-net/blame/6401d15192237dcdbc1e5daf17075ed1aa3cd8a0/sdk/identity/Azure.Identity/src/MsalClientBase.cs#L64-L72

The effect is that it broke silent authentication from token cache that was working with Azure.Identity 1.3

Here is the code:

const string akv = "https://MyKeyVault.vault.azure.net/";
string secretName = "MySecret";

const string MicrosoftTenantId = "72f988bf-86f1-41af-91ab-2d7cd011db47";

DefaultAzureCredentialOptions credentialOptions = new()
{
    // We only want Shared Token Cache and Interactive credential for MFA authentication
    ExcludeSharedTokenCacheCredential = false,  // <-- no longer works with 1.5, always falls through to next credential in the chain
    ExcludeInteractiveBrowserCredential = false,

    // We explicitly exclude all other credential types.
    ExcludeAzureCliCredential = true,
    ExcludeEnvironmentCredential = true,
    ExcludeManagedIdentityCredential = true,
    ExcludeVisualStudioCodeCredential = true,
    ExcludeVisualStudioCredential = true,
    ExcludeAzurePowerShellCredential = true,

    // Resources are in Microsoft tenant (as opposed to say AME).
    // Making it explicit just in case (to prevent potential conflict with user having authenticated to another tenant)
    InteractiveBrowserTenantId = MicrosoftTenantId,
    SharedTokenCacheTenantId = MicrosoftTenantId,
};

TokenCredential userCredentials = new DefaultAzureCredential(credentialOptions);

SecretClient sc = new SecretClient(new Uri(akv), userCredentials);
KeyVaultSecret kvs = sc.GetSecret(secretName, version: null, CancellationToken.None); // <-- prompts once with 1.3; always prompts in 1.5. If you inspect private properties of userCredentials, only in 1.3 SharedTokenCacheCredential is used.

What I found in debugger is SharedTokenCacheCredential not able to use cache because TokenCache is null below, hence it does not find any cached accounts and passes control to the next credential in chain:

//C:\Users\ayeltsov\AppData\Local\SourceServer\ec994ec8e5e8a8720a9c1a17f5a92aeb5df39eca966203725c5cc67aadc2988b\sdk\identity\Azure.Identity\src\MsalClientBase.cs

        protected async ValueTask<TClient> GetClientAsync(bool async, CancellationToken cancellationToken)
        {
            using var asyncLock = await _clientAsyncLock.GetLockOrValueAsync(async, cancellationToken).ConfigureAwait(false);
            if (asyncLock.HasValue)
            {
                return asyncLock.Value;
            }

            var client = await CreateClientAsync(async, cancellationToken).ConfigureAwait(false);

            if (TokenCache != null)  // <-- this is null
            {
                await TokenCache.RegisterCache(async, client.UserTokenCache, cancellationToken).ConfigureAwait(false);

                if (client is IConfidentialClientApplication cca)
                {
                    await TokenCache.RegisterCache(async, cca.AppTokenCache, cancellationToken).ConfigureAwait(false);
                }
            }

            asyncLock.SetValue(client);
            return client;
        }

I did not find how to initialize DefaultAzureCredentialOptions / DefaultAzureCredential so that TokenCache for SharedTokenCacheCredential gets populated.

Am I missing anything? Even if I do please note this is a breaking change resulting in authentication prompt being presented to the user every time they run the tool.

Expected behavior

Prompt for credentials once, then use cached credentials

Actual behavior

Prompt for credentials every time

Reproduction Steps

See description

Environment

.NET SDK (reflecting any global.json): Version: 6.0.103 Commit: 2d7bc7059f

Runtime Environment: OS Name: Windows OS Version: 10.0.22000 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\6.0.103\

Host (useful for support): Version: 6.0.3 Commit: c24d9a9c91

.NET SDKs installed: 3.1.417 [C:\Program Files\dotnet\sdk] 5.0.406 [C:\Program Files\dotnet\sdk] 6.0.103 [C:\Program Files\dotnet\sdk]

.NET runtimes installed: Microsoft.AspNetCore.App 3.1.23 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 3.1.23 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.23 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs: https://aka.ms/dotnet-download

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
ayeltsovcommented, Apr 5, 2022

need to worry about the AuthenticationRecord if you need the credentials to persist across runs of the application

Actually I’m saying that workaround I used in https://github.com/Azure/azure-sdk-for-net/issues/23896#issuecomment-1085047864 works across application runs and multiple applications without having to worry about AuthenticationRecord

0reactions
christothescommented, Apr 5, 2022

Yes, you only need to worry about the AuthenticationRecord if you need the credentials to persist across runs of the application, or across multiple applications using the same credentials.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Azure Identity client library for .NET
It's a known issue that VisualStudioCodeCredential doesn't work with Azure Account extension versions newer than 0.9.11. A long-term fix to this ...
Read more >
Azure SDK: What's new in the Azure Identity August 2020 ...
Environment – The DefaultAzureCredential will read account information specified via environment variables and use it to authenticate. Managed ...
Read more >
not able to fetch token using DefaultAzureCredential and ...
I am using Azure.Identity 1.7 and using VS 2022 , trying to get the token using DefaultAzureCredential, var tokenCredential = new ...
Read more >
Guidance for multi-tenant applications using the Azure ...
This blog post provides guidance on how to mitigate the potential risk of leaks in using the Azure Identity libraries within multi-tenant ...
Read more >
trying to cennect to azure through powershell, and get this ...
WARNING: Unable to acquire token for tenant 'organizations' with error 'SharedTokenCacheCredential authentication failed: AADSTS9002332: ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found