Speeding up DefaultAzureCredential authentication in local development with Azure CLI
Tags: dotnet, azure, csharp, productivity
Published: 2023-04-12 01:12:03

If you’re developing .NET applications that integrate with Microsoft Azure resources, such as [Key Vault](https://azure.microsoft.com/en-us/products/key-vault), you’re probably familiar with the `DefaultAzureCredential` class from the [Azure.Identity library](https://learn.microsoft.com/en-us/dotnet/api/overview/azure/identity-readme?view=azure-dotnet). This class simplifies the process of authenticating against Azure services by providing a unified way to retrieve access tokens. However, when working in a local development environment, you might have noticed that `DefaultAzureCredential` **can take up to 10 seconds** to retrieve your [Azure CLI credentials](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli), impacting your productivity. In this blog post, we’ll explore two ways to speed up this process: using `DefaultAzureCredentialOptions` and `ChainedTokenCredential`.

## DefaultAzureCredential overview

The `DefaultAzureCredential` class automatically selects the most appropriate credential type based on the environment in which it’s running, both in the cloud and in local development environments.

In cloud environments, `DefaultAzureCredential` usually relies on managed identities (`ManagedIdentityCredential`), simplifying the process of obtaining access tokens without the need to manage service principal credentials. For local development, `DefaultAzureCredential` usually relies on Azure CLI (`AzureCliCredential`), Visual Studio Code, or other methods to retrieve credentials.

Even so, this process can be quite slow, as it sequentially tries multiple credential types before identifying the correct one.

![The DefaultAzureCredential attempts to authenticate via the following mechanisms, in this order, stopping when one succeeds.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fihs80ejidm29s49ams6.png)

## Benchmark results

I conducted a series of benchmarks to measure the time taken by `DefaultAzureCredential` to retrieve Azure CLI local development credentials from my computer. The results show that using `DefaultAzureCredentialOptions` to exclude unnecessary underlying token credentials speeds up the process, but the fastest approach is using `ChainedTokenCredential` to chain `AzureCliCredential` and `DefaultAzureCredential`. Here are the benchmark results:

| Method                                                                      | Mean       | Error     | StdDev    |
|-----------------------------------------------------------------------------|------------|-----------|-----------|
| `DefaultAzureCredential` with no options                                    | 10,117.9 ms | 199.43 ms | 441.91 ms |
| `DefaultAzureCredential` with options to exclude unnecessary token credentials | 6,462.8 ms  | 151.35 ms | 446.26 ms |
| `ChainedTokenCredential` chaining `AzureCliCredential` and then `DefaultAzureCredential`     | 837.6 ms   | 15.92 ms  | 19.55 ms  |

_Benchmark summary table comparing the startup times for retrieving Azure CLI credentials using different approaches_

## Using DefaultAzureCredentialOptions

One way to speed up `DefaultAzureCredential` is to use `DefaultAzureCredentialOptions` to exclude unnecessary underlying token credentials. This reduces the number of token credential types that `DefaultAzureCredential` must check before finding the one that can provide an access token. The benchmark results show that this approach can speed up the process, **but it still takes around 6 seconds**:

```csharp
var tokenCredential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
    // Disable the token credential that we don't use
    ExcludeEnvironmentCredential = true,
    ExcludeInteractiveBrowserCredential = true,
    // Not everyone uses Visual Studio
    ExcludeVisualStudioCredential = true,
    ExcludeAzurePowerShellCredential = true,
    ExcludeSharedTokenCacheCredential = true,
    ExcludeVisualStudioCodeCredential = true,
});

_ = await tokenCredential.GetTokenAsync(new TokenRequestContext(new[] { "https://graph.microsoft.com/.default" }));
```


## Using ChainedTokenCredential

The fastest approach I found is using `ChainedTokenCredential` to chain `AzureCliCredential` and `DefaultAzureCredential`. This approach explicitly uses `AzureCliCredential` first, which will only succeed in a local development environment, then falls back to `DefaultAzureCredential` for cloud environments. The benchmark results show that **this method takes only about 800 milliseconds**:

```csharp
var tokenCredential = new ChainedTokenCredential(
    new AzureCliCredential(),
    new DefaultAzureCredential());

_ = await tokenCredential.GetTokenAsync(new TokenRequestContext(new[] { "https://graph.microsoft.com/.default" }));
```

## Conclusion

If you’re tired of waiting 10 seconds every time you start your application in your IDE due to `DefaultAzureCredential`‘s slow retrieval of Azure CLI credentials, I highly recommend adopting the `ChainedTokenCredential` approach. By explicitly using `AzureCliCredential` first and falling back to `DefaultAzureCredential`, you can significantly speed up the authentication process in your local development environment. Not only does this efficient solution increases your productivity, but it also ensures that the behavior in cloud environments remains unaffected.