Home > Net >  DefaultAzureCredetials can't authenticate via Visual Studio - Can't find AzureServiceAuth
DefaultAzureCredetials can't authenticate via Visual Studio - Can't find AzureServiceAuth

Time:01-14

I'm attempting to connect to an Azure Key Vault instance from a .NET 4.7 application running locally under IIS and the debugger (Visual Studio 2022 17.4.4) but am encountering the below exception(s) from the Azure.Identity package when it attempts to retrieve a token to authenticate to Azure when calling to perform a KeyVault action such as GetSecretAsync().

DefaultAzureCredential failed to retrieve a token from the included credentials. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/defaultazurecredential/troubleshoot

  • ManagedIdentityCredential authentication unavailable. Multiple attempts failed to obtain a token from the managed identity endpoint.
  • Visual Studio Token provider can't be accessed at C:\WINDOWS\system32\config\systemprofile\AppData\Local.IdentityService\AzureServiceAuth\tokenprovider.json

I need to connect to the KeyVault instance via a User Assigned Managed Identity in cloud environments such as production, whereas in development environments, we therefore need to connect via the developer's Visual Studio account to authenticate them to access the service, similarly. Perhaps I have misunderstood, but I believed this is possible via the DefaultAzureCredential option, which will try various methods of authentication in order (such as environment variables, managed identities, then Visual Studio credentials, etc) until one succeeds.

When inspecting the inner exception(s) relating to the Visual Studio Credentials flow, I see the System.Exception {System.IO.DirectoryNotFoundException} exception message states...

"Could not find a part of the path 'C:\WINDOWS\system32\config\systemprofile\AppData\Local.IdentityService\AzureServiceAuth\tokenprovider.json'.

Previously, this message had stated the below message (which I understand to be the more recent location for this file), until I attempted to run under Visual Studio 2019 for comparison, at which point, it changed to the above message.

"Could not find a part of the path C:\Users[AppPoolName]\AppData\Local.IdentityService\AzureServiceAuth\tokenProvider.json".

At first, I noticed the path didn't exist from .IdentityService onward, and so followed the suggestion on this MSFT forum post to restore the AppAuthentification extension from VS2019 into VS2022's configuration to restore the C:\Users\<AppPoolName>\AppData\Local\.IdentityService\AzureServiceAuth\tokenprovider.json file and providers the TokenProviders as a path to C:\Program Files (x86)\Microsoft Visual Studio\<version>\Enterprise\Common7\IDE\Extensions\<random dir name>\TokenService\Microsoft.Asal.TokenService.exe. On the next build, I noticed .IdentityService had been created, but not the proceeding directory or file.

I then tried logging out and into Visual Studio a number of times, but this did not seem to create the remaining missing directory and file. Creating the directory and file manually of course resolve the System.IO.DirectoryNotFoundException, but the error message then informs me that the file schema is incorrect. I'm unable to find an example with the correct schema and values.

In terms of client configuration options, I've been explicitly limiting the modes of authentication flow to just ManagedIdentity and VisualStudioCredential for simplicity after noticing other methods (e.g. AzureCLI and Azure PowerShell Module` also failed, despite being logged in to them).

_client = new SecretClient(new Uri(options.KeyVaultUri), new DefaultAzureCredential(
    new DefaultAzureCredentialOptions
    {
        ExcludeManagedIdentityCredential = false,
        ExcludeVisualStudioCredential = false,
        ExcludeInteractiveBrowserCredential = true,
        ExcludeAzurePowerShellCredential = true,
        ExcludeAzureCliCredential = true,
        ExcludeEnvironmentCredential = true,
        ExcludeVisualStudioCodeCredential = true,
        ExcludeSharedTokenCacheCredential = true,
        ManagedIdentityClientId = options.ManagementIdentityClientId
    }
));

I've also tried the suggestions on Azure SDK GitHub Issue #4590 of settings setProfileEnvironment and loadUserProfile to true in case it's an IIS permissions issue, but this made no difference - the same errors continue.

Finally, the only other reference I've found to the tokenProvider.json file is in Microsoft's documentation for App Authentication, but the re-authenticate button doesn't exist in the Tools > Options > Azure Service Authentication window as suggested.

"If you run into problems using Visual Studio, such as errors that involve the token provider file, carefully review the preceding steps.

You may need to reauthenticate your developer token. To do so, select Tools > Options, and then select Azure Service Authentication. Look for a Re-authenticate link under the selected account. Select it to authenticate."

As I'm able to locate C:\Program Files (x86)\Microsoft Visual Studio\<version>\Enterprise\Common7\IDE\Extensions\<random dir name>\TokenService\Microsoft.Asal.TokenService.exe and its related configuration file, I suspect it's the missing tokenProvider.json file that's the issue, but I'm not aware of what is responsible for creating that, nor what it should contain.

Any insight or pointers would be appreciated.

Notable packages and their versions in use:

Edit (1)

As one might expect, I'm able to configure an alternative flow to work by granting an RBAC record upon the Key Vault for an Azure AD Application Registration and then using the ClientSecretCredential flow in place of the DefaultAzureCredentials flow (as below). But this doesn't solve the problem in the best way so I'd be interested if anyone can spot where I'm going wrong with the DefaultAzureCredentials flow, if at all.

_client = new SecretClient(new Uri(options.KeyVaultUri), 
    new ClientSecretCredential(options.TenantId, options.ClientId, options.Secret)
);

CodePudding user response:

Having found this question on SO, I found that tokenProvider.json existed in the same directory under C:\Users\<local user account> (via %LOCALAPPDATA%.IdentityService\AzureServiceAuth\) and was able to analyse it for reference and duplicate it to the IIS.

As suggested by Johnny5, it seems VisualStudioCredentials executes as the signed-in domain user, but IIS is running as the ApplicationPoolIdentity, hence it doesn't access the file under the domain user location and doesn't create one as it's not signed into Visual Studio. After a little research on how to alter this, I was able to set the IIS Application Pool identity as my domain user which matched the signed-in Visual Studio account.

To do this, follow these steps

  • Open IIS Manager > Go to Application Pools
  • Right-click the relevant pool, then click Advanced Settings...
  • Click the 3-dot button next to the Identity settings (likely ApplicationPoolIdentity)
  • Select Custom Account and enter your credentials (including any domain prefix - e.g. DOMAIN\MyUser)

If you aren't sure of your domain, open a command prompt and enter echo %USERDOMAIN% to find it.

I then set the SecretClient authentication flow back to utilise DefaultAzureCredential like so, re-tested locally, and success - secrets retrieved.

  _client = new SecretClient(new Uri(options.KeyVaultUri), new DefaultAzureCredential(
      new DefaultAzureCredentialOptions()
      {
          ExcludeEnvironmentCredential = true,
          ExcludeVisualStudioCodeCredential = true,
          ExcludeAzureCliCredential = true,
          ExcludeAzurePowerShellCredential = true,
          ExcludeSharedTokenCacheCredential = true,
          ExcludeInteractiveBrowserCredential = true,
          ExcludeManagedIdentityCredential = false,
          ExcludeVisualStudioCredential = false,
          ManagedIdentityClientId = options.ManagementIdentityClientId,
      }));
  • Related