Blog

DefaultAzureCredential: One Login For Key Vault And Graph

Authenticating to different Azure services used to mean juggling different methods. The Azure SDK has brought that under one roof with a unified credential type, and it is worth knowing how to drive it.

The `DefaultAzureCredential` class from the Azure Identity library is the new standard way to grab tokens for Azure AD across services. It works for Key Vault, it works for Graph, and it tries a sensible set of options in order so you do not have to.

What happened

  • `DefaultAzureCredential` is a `TokenCredential` from the Azure Identity library that works across the Azure SDK.
  • It tries `EnvironmentCredential`, `ManagedIdentityCredential`, `SharedTokenCacheCredential`, and `InteractiveBrowserCredential` in order, where enabled.
  • It can be used directly with `SecretClient` for Key Vault version 4 clients.
  • For Graph, wrap the access token in a `DelegateAuthenticationProvider` for `GraphServiceClient`.
  • For local development, it picks up credentials from your IDE's shared token cache, usually Visual Studio.

Background: why this exists

Older Azure code often reached for `Microsoft.Azure.Services.AppAuthentication` and its `AzureServiceTokenProvider` class. That worked, but each service had its own pattern, and switching between local dev, CI, and production meant fiddling with connection strings or environment variables.

The newer Azure Identity library flattens that. One credential type, multiple underlying sources, sensible defaults. You build your SDK clients with the credential and the SDK figures out how to get a token.

Credential chain comparison

Environment Winning Credential How to Configure
Local dev (Visual Studio) `SharedTokenCacheCredential` Sign into Visual Studio with the target account; set `SharedTokenCacheUsername` if multiple accounts exist
CI / Containers `EnvironmentCredential` Set `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID`
Azure host (App Service, VMs) `ManagedIdentityCredential` Enable Managed Identity in the Azure portal; no credentials to store
Interactive / troubleshooting `InteractiveBrowserCredential` Must be explicitly enabled; opens browser login

Our analysis

The win here is consistency. Once you wire up `DefaultAzureCredential` once, the same instance works for Key Vault, Graph, Storage, and any newer SDK client that takes a `TokenCredential`. You stop writing per-service authentication code.

The trade-off is in local development. `DefaultAzureCredential` will happily pick the wrong account if you have several signed in. If your Visual Studio has your personal email and your work account, and your personal email is tied to an Azure subscription without access to the Key Vault, you will get auth errors that look like permission problems but are really identity problems. The fix is to set `SharedTokenCacheUsername` on the credential options so it uses the account you actually want.

There is also the `EnvironmentCredential` path. If you set the three environment variables, the credential will use them and skip the cache entirely. That is useful for CI runners and containers. But for local debugging, the IDE cache is usually the path of least resistance.

For Key Vault, the version 4 client takes `TokenCredential` directly. Older version 3 code needs a small adapter: build the credential, call `GetToken` with the right scope, return the token string. More boilerplate, but the same logic.

A worked example

Say you are writing a .NET app that reads a secret from Key Vault and then calls Microsoft Graph to look up a user. Start with the credential:

“`csharp

Var credential = new DefaultAzureCredential();

Var secretClient = new SecretClient(

New Uri("https://identitytest.vault.azure.net"),

Credential);

Var secret = await secretClient.GetSecretAsync("MySecret");

“`

That part is clean. For Graph, you do not get a constructor that takes `TokenCredential` directly, so wrap the token:

“`csharp

Var token = await credential.GetToken(

New Azure.Core.TokenRequestContext(

New[] { "https://graph.microsoft.com/.default" }));

Var graphClient = new GraphServiceClient(

New DelegateAuthenticationProvider((request) => {

Request.Headers.Authorization =

New AuthenticationHeaderValue("bearer", token.Token);

Return Task.CompletedTask;

}));

“`

For local dev, if you hit an auth error and you have multiple Visual Studio accounts, wrap the credential with the option:

“`csharp

Var options = new DefaultAzureCredentialOptions {

SharedTokenCacheUsername = "you@yourcompany.com"

};

Var credential = new DefaultAzureCredential(options);

“`

Gate that with `#if DEBUG` if you want it only during local runs.

Bottom line

`DefaultAzureCredential` is the default for a reason. Use it. Pin the right account in local dev with `SharedTokenCacheUsername`, fall back to environment variables in CI, and you will not need to write auth glue again.

Key takeaways

  • Use `DefaultAzureCredential` as your default credential across Azure SDK clients.
  • For local dev, set `SharedTokenCacheUsername` to avoid picking the wrong IDE account.
  • Use environment variables for `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, and `AZURE_TENANT_ID` in CI.
  • Version 4 of KeyVaultClient takes `TokenCredential` directly; version 3 needs an adapter.
  • For Graph, wrap the access token in `DelegateAuthenticationProvider` since there is no direct `TokenCredential` constructor.

Frequently asked questions

What does `DefaultAzureCredential` actually do?

It tries a chain of credential sources in order and returns the first one that produces a valid Azure AD token.

Do I need to enable each credential type?

Some, like `InteractiveBrowserCredential`, are off by default. The others run automatically based on what is available in the environment.

How do I use it with older Key Vault client code?

Build the credential, call `GetToken` with the Key Vault scope, and pass the token string to your version 3 client through its authentication callback.

Why does local auth fail when I have multiple Visual Studio accounts?

The shared token cache may pick an account that does not have access to your resource. Set `SharedTokenCacheUsername` to pin the right one.

Can I use this in production?

Yes. In production, `ManagedIdentityCredential` is usually the path that wins, with no secrets to manage.

Related