← Back to all posts

Getting Started with Azure Key Vault in .NET

Getting Started with Azure Key Vault in .NET

Reading Time: 5 minutes

The Problem

Secrets management is one of the most common security pitfalls in software development. How many times have you seen this in a codebase?

// appsettings.json - ❌ NEVER do this
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=prod-server;Database=MyApp;User Id=admin;Password=SuperSecret123!"
  },
  "Stripe": {
    "SecretKey": "sk_live_abc123xyz789..."
  },
  "SendGrid": {
    "ApiKey": "SG.real-api-key-here..."
  }
}

These secrets end up committed to source control, shared in Slack, emailed around, and baked into Docker images. Anyone with access to the repo - or who ever had access - can see them. When a developer leaves the company, do you rotate every secret they could have seen? Probably not.

The risks are real:

  • Secrets in git history are permanent even after deletion
  • Developers on local machines have production credentials
  • No audit trail of who accessed which secret
  • Rotating secrets requires code changes and redeployments

The Solution

Azure Key Vault provides a centralized, secure secret store with:

  • Encryption at rest and in transit
  • Fine-grained access control via Azure RBAC
  • Full audit logging of all secret accesses
  • Secret versioning and rotation support
  • Seamless integration with the .NET SDK

Setting Up Azure Key Vault

Before writing any code, you need to create a Key Vault in Azure:

  1. Log into the Azure Portal
  2. Click Create a resource and search for Key Vault
  3. Click Create and fill in the details:
    • Resource group: Select or create one
    • Key vault name: Must be globally unique (e.g., myapp-kv-prod)
    • Region: Choose the same region as your application
    • Pricing tier: Standard is sufficient for secrets
  4. On the Access configuration tab, select Azure role-based access control (RBAC)
  5. Click Review + create, then Create
  6. Once created, navigate to Access control (IAM) and add yourself as Key Vault Secrets Officer
  7. Go to Secrets and add your secrets (e.g., ConnectionStrings--DefaultConnection)

Note: Key Vault secret names use -- instead of : for nested configuration keys, because : is not allowed in secret names. The .NET configuration provider automatically handles this mapping.

Installing NuGet Packages

Add the required packages to your project:

dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets
dotnet add package Azure.Identity
  • Azure.Extensions.AspNetCore.Configuration.Secrets - integrates Key Vault with IConfiguration
  • Azure.Identity - provides DefaultAzureCredential for authentication

Configuring Key Vault in Program.cs

The cleanest way to add Key Vault is in your application’s configuration setup:

using Azure.Identity;

var builder = WebApplication.CreateBuilder(args);

// Add Key Vault to the configuration pipeline
var keyVaultUri = builder.Configuration["KeyVault:Uri"]
    ?? throw new InvalidOperationException("KeyVault:Uri is not configured");

builder.Configuration.AddAzureKeyVault(
    new Uri(keyVaultUri),
    new DefaultAzureCredential()
);

// Now all Key Vault secrets are available via IConfiguration
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

var app = builder.Build();
app.Run();

Store only the Key Vault URI in your appsettings.json - it’s not a secret:

{
  "KeyVault": {
    "Uri": "https://myapp-kv-prod.vault.azure.net/"
  }
}

Reading Secrets in Your Services

Once Key Vault is wired into IConfiguration, you access secrets exactly the same way as any other configuration value:

public class StripePaymentService : IPaymentService
{
    private readonly string _secretKey;
    private readonly ILogger<StripePaymentService> _logger;

    public StripePaymentService(
        IConfiguration configuration,
        ILogger<StripePaymentService> logger)
    {
        _secretKey = configuration["Stripe--SecretKey"]
            ?? throw new InvalidOperationException("Stripe secret key is not configured");
        _logger = logger;
    }

    public async Task<PaymentResult> ChargeAsync(decimal amount, string token)
    {
        // Use _secretKey safely - it came from Key Vault, never from code
        _logger.LogInformation("Processing payment of {Amount}", amount);
        // ... Stripe API call
    }
}

For strongly-typed configuration, use the Options pattern:

// Options class
public class StripeOptions
{
    public const string SectionName = "Stripe";
    public string SecretKey { get; set; } = string.Empty;
    public string PublishableKey { get; set; } = string.Empty;
}

// In Program.cs
builder.Services.Configure<StripeOptions>(
    builder.Configuration.GetSection(StripeOptions.SectionName));

// In your service
public class StripePaymentService : IPaymentService
{
    private readonly StripeOptions _options;

    public StripePaymentService(IOptions<StripeOptions> options)
    {
        _options = options.Value;
    }
}

Local Development with DefaultAzureCredential

DefaultAzureCredential is the magic that makes this work seamlessly across environments. It tries a chain of authentication methods in order:

  1. Environment variables (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID)
  2. Workload Identity (Kubernetes)
  3. Managed Identity (Azure VMs, App Service, Functions, Container Apps)
  4. Azure CLI - az login on your local machine ✅
  5. Visual Studio credentials
  6. VS Code credentials

For local development, simply run az login once:

az login
az account set --subscription "Your Subscription Name"

Then grant your personal Azure account the Key Vault Secrets User role on the Key Vault in the Azure Portal. Your local dev machine will automatically authenticate using your Azure CLI session - no secrets in environment variables needed!

In production on Azure App Service or Azure Container Apps, assign a Managed Identity to your app and grant it Key Vault Secrets User - no credentials needed in production either.

Summary

Azure Key Vault with DefaultAzureCredential gives you a production-grade secrets management solution with minimal code:

  • No secrets in source control - only the Key Vault URI is in config
  • No secrets on developer machines - Azure CLI auth handles local dev
  • No secrets in production environments - Managed Identity handles Azure hosting
  • Full audit trail - every secret access is logged in Azure Monitor
  • Easy rotation - update the secret in Key Vault, no code changes needed

This pattern scales from a small startup to enterprise - and your future self (and security auditors) will thank you for it.

References