Managed Identity Authentication
Overview
Azure Key Vault supports authentication via Managed Identities, eliminating the need to store credentials in code or configuration. This is the recommended approach for Azure-hosted workloads accessing Key Vault secrets, keys, and certificates.
System-Assigned vs User-Assigned Identity
| Feature | System-Assigned | User-Assigned |
|---|---|---|
| Lifecycle | Tied to the resource | Independent |
| Sharing | One per resource | Can be shared across resources |
| Use case | Single-purpose workloads | Multi-resource scenarios |
| Deletion | Deleted with resource | Must be explicitly deleted |
When to Use Each
- System-assigned: Simple scenarios where one resource needs Key Vault access (e.g., a single App Service).
- User-assigned: When multiple resources (Functions, App Services, VMs) need the same identity and permissions.
DefaultAzureCredential
The DefaultAzureCredential class from the Azure Identity SDK provides a unified authentication flow that works across local development and production.
Authentication Chain
- Environment variables
- Workload Identity (Kubernetes)
- Managed Identity (system or user-assigned)
- Visual Studio credential
- Visual Studio Code credential
- Azure CLI credential
- Azure PowerShell credential
- Azure Developer CLI credential
- Interactive browser (disabled by default)
.NET Example
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
var credential = new DefaultAzureCredential();
var client = new SecretClient(
new Uri("https://my-vault.vault.azure.net/"),
credential
);
KeyVaultSecret secret = await client.GetSecretAsync("DatabaseConnectionString");
string connectionString = secret.Value;
Python Example
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
credential = DefaultAzureCredential()
client = SecretClient(
vault_url="https://my-vault.vault.azure.net/",
credential=credential
)
secret = client.get_secret("DatabaseConnectionString")
print(secret.value)
Node.js Example
const { DefaultAzureCredential } = require("@azure/identity");
const { SecretClient } = require("@azure/keyvault-secrets");
const credential = new DefaultAzureCredential();
const client = new SecretClient(
"https://my-vault.vault.azure.net/",
credential
);
const secret = await client.getSecret("DatabaseConnectionString");
console.log(secret.value);
Enabling Managed Identity
Azure CLI — System-Assigned
# Enable on App Service
az webapp identity assign --name my-app --resource-group my-rg
# Enable on Azure Function
az functionapp identity assign --name my-func --resource-group my-rg
Azure CLI — User-Assigned
# Create the identity
az identity create --name my-identity --resource-group my-rg
# Assign to App Service
az webapp identity assign \
--name my-app \
--resource-group my-rg \
--identities /subscriptions/{sub}/resourceGroups/my-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-identity
Granting Key Vault Access
After enabling managed identity, grant it access to Key Vault:
# Get the principal ID
PRINCIPAL_ID=$(az webapp identity show --name my-app --resource-group my-rg --query principalId -o tsv)
# Assign RBAC role (recommended over access policies)
az role assignment create \
--role "Key Vault Secrets User" \
--assignee $PRINCIPAL_ID \
--scope /subscriptions/{sub}/resourceGroups/my-rg/providers/Microsoft.KeyVault/vaults/my-vault
Specifying User-Assigned Identity in Code
When using a user-assigned identity, pass the client ID explicitly:
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
ManagedIdentityClientId = "your-user-assigned-client-id"
});
credential = DefaultAzureCredential(
managed_identity_client_id="your-user-assigned-client-id"
)
Local Development
For local development, DefaultAzureCredential falls back to Azure CLI or Visual Studio credentials:
# Login with Azure CLI
az login
# Set the subscription context
az account set --subscription "my-subscription"
No code changes needed — the same DefaultAzureCredential works locally and in production.
Common Errors
| Error | Cause | Fix |
|---|---|---|
ManagedIdentityCredential authentication unavailable | Identity not enabled | Enable managed identity on the resource |
403 Forbidden | Missing RBAC role | Assign Key Vault Secrets User role |
SecretNotFound | Wrong vault URL or secret name | Verify vault URL and secret name |
CredentialUnavailableError | No valid credential in chain | Ensure az login locally or identity enabled in Azure |
Best Practices
- Always use Managed Identity over connection strings or client secrets for Azure-hosted workloads.
- Prefer RBAC over vault access policies for granular, auditable permissions.
- Use user-assigned identities when multiple services share the same access pattern.
- Never log secret values — reference them by name in diagnostics.
- Test locally with
az loginto validate the credential chain before deploying. - Set
AZURE_CLIENT_IDenvironment variable in App Service when using user-assigned identity.
Summary
Managed Identity with DefaultAzureCredential is the zero-secret approach to Key Vault authentication. It works seamlessly across development and production, eliminates credential management overhead, and integrates with Azure RBAC for fine-grained access control.