Want to protect sensitive data in your ASP.NET Core apps? Here's what you need to know:
The Quick Version: Your app needs a different secret management approach for development vs production:
- Development: Use Secret Manager tool
- Production: Use Azure Key Vault or environment variables
- Never store secrets in source code or config files
What You'll Learn:
Stage | Tool | Best For |
---|---|---|
Development | Secret Manager | API keys, connection strings |
Testing | Environment Variables | Service credentials |
Production | Azure Key Vault | Encryption keys, passwords |
Key Steps to Implement:
- Development:
dotnet user-secrets init
dotnet user-secrets set "key" "value"
- Production:
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{vaultName}.vault.azure.net/"),
new DefaultAzureCredential());
Common Mistakes to Avoid:
- Storing secrets in source code
- Using Secret Manager in production
- Keeping plain text passwords in config files
- Sharing development secrets across teams
This guide shows you how to set up proper secret management from development through production, with real code examples and step-by-step instructions.
Related video from YouTube
Basics of Secret Management
What Are Secrets?
Secrets in ASP.NET Core apps are sensitive data you need to protect. Think passwords, API keys, and other private info that shouldn't be public.
Here are the main types of secrets you'll deal with:
Secret Type | Description | Example |
---|---|---|
API Keys | External service tokens | auth0:clientId: "x8f9g2h3j4" |
Connection Strings | Database access info | "DbConnection": "Server=myserver;Database=mydb" |
Service Credentials | System login details | "ServiceUser": "admin123" |
Encryption Keys | Data security keys | "EncryptionKey": "base64string..." |
How Secret Manager Works
The .NET Secret Manager keeps your secrets in JSON format - far away from your project files. Here's where it stores them:
Operating System | Location |
---|---|
Windows | %APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json |
Mac/Linux | ~/.microsoft/usersecrets/<user_secrets_id>/secrets.json |
"One of the most important features in building secure applications is to make sure that you keep your secrets safe." - Ervis Trupja, Web Developer
Let's break down what you need to know:
Your secrets live as key-value pairs in secrets.json
. Here's what that looks like:
{
"Auth0": {
"Domain": "mydomain.auth0.com",
"ClientId": "abc123",
"ClientSecret": "xyz789"
}
}
Quick Setup:
- Type
dotnet user-secrets init
- Add secrets with
dotnet user-secrets set "key" "value"
- Add setup steps to your README
NEVER put secrets in:
- Your code
- Config files
- Public repos
- Shared drives
Here's the thing about Secret Manager: It's perfect for development but NOT for production. Why? Because:
- Secrets aren't encrypted
- Anyone with machine access can read them
For production, stick to environment variables or secure vaults. Keep those secrets OUT of your app completely.
Setting Up Your Environment
Here's how to set up your development environment from scratch:
Core Tools
You'll need these 3 tools to get started:
Tool | Purpose | Installation Command |
---|---|---|
.NET SDK | Core development platform | winget install Microsoft.DotNet.SDK.7 |
Visual Studio 2019+ | IDE with built-in tools | Download from Visual Studio website |
Git | Version control | winget install Git.Git |
Project Setup
Let's break this down into simple steps:
1. Create Your Project
Fire up Visual Studio and run:
dotnet new webapi -n SecureSecrets
cd SecureSecrets
2. Add These NuGet Packages
Package Name | What It Does |
---|---|
Microsoft.Extensions.Configuration | Handles basic configs |
Microsoft.Extensions.Configuration.Json | Manages JSON files |
Microsoft.Extensions.Configuration.UserSecrets | Keeps secrets safe |
3. Set Up Environment
Windows users:
$Env:ASPNETCORE_ENVIRONMENT = "Development"
Mac/Linux users:
export ASPNETCORE_ENVIRONMENT=Development
4. Update Program.cs
Drop this code into your Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true)
.AddEnvironmentVariables()
.AddUserSecrets<Program>();
5. Configure Launch Settings
Your launchSettings.json
should match this:
{
"profiles": {
"Development": {
"commandName": "Project",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Scott Hunter, Director of Program Management for .NET, puts it this way: "Setting up proper environment configurations is the first line of defense in securing your application secrets. The environment setup determines how your application handles sensitive data across different stages of development."
Here's the key: Keep your development environment open for testing, but lock down staging and production tight. No exceptions.
Working with Secret Manager
Secret Manager helps you handle sensitive data during ASP.NET Core development. Here's what you need to know:
Setting Up Secret Manager
First, open your terminal and run:
dotnet user-secrets init
This adds to your .csproj file:
<PropertyGroup>
<UserSecretsId>your-unique-guid-here</UserSecretsId>
</PropertyGroup>
Then, in Program.cs
, add:
builder.Configuration.AddUserSecrets<Program>();
Key Commands
Here are the main commands you'll use:
Command | What It Does | How to Use It |
---|---|---|
set |
Adds a secret | dotnet user-secrets set "ApiKey" "abc123" |
list |
Shows secrets | dotnet user-secrets list |
remove |
Deletes a secret | dotnet user-secrets remove "ApiKey" |
clear |
Removes all | dotnet user-secrets clear |
Want to add multiple secrets? Use JSON:
cat ./secrets.json | dotnet user-secrets set
What You Should Know
Secret Manager has some limits:
What | Details |
---|---|
Where It Stores | Windows: %APPDATA%\Microsoft\UserSecrets\<user_secrets_id> Linux/Mac: ~/.microsoft/usersecrets/<user_secrets_id> |
Security | Not encrypted - don't use in production |
Project Scope | Tied to your UserSecretsId |
When It Works | Development mode only |
Here's how to use secrets in code:
public class UserCredentials
{
public string UserName { get; set; }
public string Password { get; set; }
}
services.Configure<UserCredentials>(
configuration.GetSection(nameof(UserCredentials)))
.AddSingleton(env);
"Secret Manager is for development ONLY. For production, use environment variables, Azure Key Vault, or other secure storage." - Microsoft Docs
Your secrets file structure:
{
"ConnectionStrings:SQLServerIdentityConnection": "your-connection-string",
"Facebook:AppId": "your-facebook-id",
"Facebook:AppSecret": "your-facebook-secret"
}
Setting Up Environment Variables
Here's how to set up environment variables in ASP.NET Core:
Local Development Setup
Start by adding this to your Program.cs
:
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", true)
.AddEnvironmentVariables()
.Build();
Here's how to set variables on different systems:
OS | Command | Example |
---|---|---|
Windows CMD | set |
set ConnectionStrings__sqlConnection="server=.\SQLEXPRESS;database=MyApp" |
PowerShell | $Env: |
$Env:ASPNETCORE_ENVIRONMENT = "Development" |
Linux/Mac | export |
export ConnectionStrings__sqlConnection="server=localhost;database=MyApp" |
Using Visual Studio? Add this to launchSettings.json
:
{
"profiles": {
"WebApi": {
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ConnectionStrings__DefaultConnection": "Server=localhost;Database=MyApp"
}
}
}
}
Production Setup
Here's what you need for each platform:
Platform | Setup Method | Notes |
---|---|---|
Azure App Service | Application Settings | Overrides local configs |
Docker | Environment file | Use docker-compose.yml |
IIS | Web.config | Under aspNetCore node |
For Docker, add this to your file:
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ConnectionStrings__DefaultConnection=Server=prod-db;Database=MyApp
For IIS, use this in web.config
:
<aspNetCore>
<environmentVariables>
<environmentVariable name="ConnectionStrings__DefaultConnection"
value="Server=prod-db;Database=MyApp" />
</environmentVariables>
</aspNetCore>
Quick tips:
- Use double underscores (
__
) for hierarchical keys - Set machine-level variables for persistence
- Drop development settings in production
- Keep sensitive data OUT of source control
- Use different variables per environment
- Store production variables securely
- Check your environment-specific files
Adding Azure Key Vault
Here's how to use Azure Key Vault to store your app secrets in the cloud with ASP.NET Core.
Set Up Your Key Vault
First, grab these NuGet packages:
dotnet add package Azure.Identity
dotnet add package Azure.Security.KeyVault.Secrets
Head to Azure Portal and create your vault:
Do This | Here |
---|---|
Open | Azure Portal → Create Resource |
Find | "Key Vault" in search |
Enter | Name, subscription, resource group |
Finish | Hit "Review + Create" |
Now connect to your vault:
var client = new SecretClient(
new Uri("https://<your-vault-name>.vault.azure.net/"),
new DefaultAzureCredential(),
new SecretClientOptions {
Retry = {
Delay = TimeSpan.FromSeconds(2),
MaxRetries = 5,
Mode = RetryMode.Exponential
}
}
);
Add this to your Program.cs
:
builder.Configuration.AddAzureKeyVault(
new Uri($"https://{keyVaultName}.vault.azure.net/"),
new DefaultAzureCredential());
Set Up Managed Identities
Managed identities let you skip storing credentials. Here's what to do:
Action | Run This |
---|---|
Set up identity | az webapp identity assign --name "<app-name>" --resource-group "<group-name>" |
Set permissions | az role assignment create --role "Key Vault Secrets User" --assignee "<app-id>" --scope "<vault-resource-id>" |
In Key Vault, add these permissions:
- Get Secrets
- List Secrets
Get your secrets in code:
var secretClient = new SecretClient(
new Uri("<vault-url>"),
new DefaultAzureCredential());
KeyVaultSecret secret = await secretClient.GetSecretAsync("<secret-name>");
string secretValue = secret.Value;
Quick tips:
- Pick system-assigned identities for single apps
- Set up retry logic for network hiccups
- Store vault URLs in config
- Double-check secret access after setup
sbb-itb-29cd4f6
Secret Management Tips
Here's how to keep your app's secrets safe and secure in ASP.NET Core:
Encrypting Config Values
ASP.NET Core gives you several ways to protect sensitive data. Here's what works best for different types of secrets:
Data Type | Protection Method | Usage |
---|---|---|
Authentication Cookies | Built-in DPAPI | ASP.NET Core handles this automatically |
Connection Strings | Azure Key Vault | Keep them safe in the cloud |
API Keys | Environment Variables | Isolate at the process level |
User Secrets | Secret Manager | Local dev only - don't use in production |
Using AWS? Here's how to encrypt with KMS:
aws kms encrypt --cli-binary-format raw-in-base64-out --key-id "key-id" --plaintext "YOUR_SECRET"
Then pop the encrypted value in your config:
{
"Database": {
"Password": "AQICAHhDR/VQh6Ap...rfyKsKCG2h6WVK8="
}
}
Setting Up Access Rules
Here's what you NEED to do to lock down your secrets:
Rule | What to Do |
---|---|
Separate Environment Secrets | Use different secrets for each environment |
Key Rotation | Switch secrets every 90 days |
Access Logging | Track who's accessing what |
Least Privilege | Give only the access that's needed |
"Never store passwords or other sensitive data in source code." - Microsoft Learn
Keep your secrets safe:
- Add
appsettings.json
and.env
to.gitignore
- Use your OS's key vault
- Create separate apps for key generation
- Watch those production logs
"The Secret Manager tool doesn't encrypt the stored secrets and shouldn't be treated as a trusted store." - Microsoft Learn
When working with other services:
Service | What to Do |
---|---|
Azure Resources | Key Vault + managed identities |
Database Access | Encrypt those connection strings |
API Integration | Change keys without touching the app |
User Authentication | Set up ASP.NET Core Identity right |
Testing Your Setup
Here's how to test if your secrets work correctly.
Writing Tests for Secrets
Here's what you need to set up tests:
Test Type | Setup Method | Example |
---|---|---|
Unit Tests | .runsettings file |
Define variables in XML configuration |
Integration Tests | Environment Variables | Set via dotnet test command |
Azure Key Vault Tests | Managed Identity | Use test instance of Key Vault |
Here's a simple test with xUnit and Shouldly:
public class SecretTests
{
private readonly IConfiguration _config;
public SecretTests(IConfiguration config)
{
_config = config;
}
[Fact]
public void ShouldRetrieveSecret()
{
_config.GetValue<string>("MySecret").ShouldNotBeNull();
}
}
For VS Code, add this to .vscode/settings.json
:
{
"csharp.unitTestDebuggingOptions": {
"env": {
"MySecret": "test-value"
}
}
}
Security Checks
Make sure your secrets are safe with these checks:
Check | How to Test | Pass Criteria |
---|---|---|
Access Control | Try accessing with wrong permissions | Access denied |
Environment Isolation | Check each environment's secrets | Different values per environment |
Key Vault Integration | Test managed identity access | Successful secret retrieval |
User Secrets | Move connection string to secrets | App connects to database |
Test Azure Key Vault access like this:
public class KeyVaultTests
{
[Fact]
public async Task ShouldAccessKeyVault()
{
var client = new SecretClient(
new Uri("https://your-vault.vault.azure.net/"),
new DefaultAzureCredential());
var secret = await client.GetSecretAsync("test-secret");
Assert.NotNull(secret.Value);
}
}
After testing:
- Delete test secrets from Key Vault
- Clear environment variables
- Reset user secrets
- Remove test certificates
"The User Secrets file is located outside the project path, reducing the risk of sensitive data being checked into source control." - Microsoft Learn
Next Steps
Here's what you need to do after setting up your secrets:
Action | What to Do | When |
---|---|---|
Rotate Secrets | Switch out API keys and passwords | Every 60 days |
Check Access | Update Key Vault access rules | Monthly |
Watch Costs | Check Key Vault usage ($0.03/10K requests) | Weekly |
Check Security | Look for weird access patterns | Daily |
Keep Your Setup Running Smooth
1. Watch Your Spending
Here's a heads up: Key Vault costs can sneak up on you. If you check for new values 12 times per minute, that's 518,400 monthly requests. At $0.03 per 10,000 requests, you're looking at $1.56 per secret.
2. Lock Down Your Access
What to Set Up | Where to Do It | What It Does |
---|---|---|
Firewall | Azure Portal | Blocks unwanted IPs |
RBAC | Azure AD | Sets who gets in |
Access Rules | Key Vault | Controls app access |
Delete Protection | Key Vault Settings | Stops accidents |
3. Split Up Your Environments
Keep things separate and clean:
Environment | Name It | Who Gets In |
---|---|---|
Dev | dev-kv-[app] | Dev team |
Test | test-kv-[app] | QA folks |
Production | prod-kv-[app] | Admins only |
Set It Up in PowerShell
Here's the code to load your secrets from JSON:
$json = Get-Content 'C:\\SecretPath\\secret.json' | ConvertFrom-Json
foreach($parentProp in $json.PSObject.Properties){
foreach($childProp in $parentProp.Value.PSObject.Properties){
$envVarName = $parentProp.Name + '__' + $childProp.Name
[System.Environment]::SetEnvironmentVariable($envVarName, $childProp.Value, 'Machine')
}
}
Quick Tips
- Each environment needs its own secrets
- Look at your access logs every day
- Clean up old secrets after you change them
- Keep your IIS variables up to date
- Track what you're spending in Azure
For IIS? Name your variables like this: [object]__[property]
(Like ConnectionStrings__MyDBContext
)
FAQs
What is the secret manager tool in an ASP.NET Core project?
The Secret Manager tool in ASP.NET Core helps you store sensitive data while you're building your app. It puts your secrets in a JSON file at %APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
on Windows - away from your project files.
Think of it like a safe for your development passwords and API keys. It's NOT for production use - just for when you're coding.
How to store secrets in production environment?
Here's what you should use in each environment:
Environment | Storage Method | Why It Works |
---|---|---|
Development | Secret Manager Tool | Keeps secrets off GitHub |
Testing | Azure Key Vault | Controls who gets access |
Production | Environment Variables or Azure Key Vault | Locks down secrets at server level |
"Don't bundle secrets with your app code. In production, get them through environment variables or Azure Key Vault." - CyberArk Developer
What's the real difference between user secrets and environment variables?
Let's break it down:
Feature | User Secrets | Environment Variables |
---|---|---|
Where It's Stored | Local JSON file | Server-level |
Security Type | Plain text, your machine only | Plain text, whole system |
When to Use | While coding | In production |
Who Controls It | Just you | System-wide |
Here's the bottom line: User secrets are ONLY for development. They're perfect when you're coding, but NOT for your live app.
"The Secret Manager tool is built for one thing: keeping sensitive data safe during development." - Ottorino Bruni, Author