Wednesday, November 12, 2025

thumbnail

Managing Secrets and Configuration in .NET Core

๐Ÿ” Introduction


In every .NET Core (now .NET 6/7/8) application, you need to store configuration data — things like:


Database connection strings


API keys (Stripe, SendGrid, etc.)


Cloud credentials


JWT signing keys


Third-party service secrets


However, storing secrets directly in code or config files (like appsettings.json) is a major security risk.


That’s where .NET’s configuration system and secret management tools come in.


⚙️ Configuration System Overview


.NET Core uses a configuration provider model — meaning you can load configuration values from multiple sources, in this order (by default):


appsettings.json


appsettings.{Environment}.json (e.g., appsettings.Development.json)


Environment variables


User secrets (in development)


Command-line arguments


Azure Key Vault or other secret stores


๐Ÿ’ก Later sources override earlier ones, so you can replace defaults securely per environment.


๐Ÿ—‚️ 1. Using appsettings.json


Basic app configuration lives in appsettings.json:


{

  "ConnectionStrings": {

    "DefaultConnection": "Server=localhost;Database=MyApp;Trusted_Connection=True;"

  },

  "JwtSettings": {

    "Key": "dev-secret-key",

    "Issuer": "MyApp"

  }

}



Then, access configuration in your code:


var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

var jwtKey = builder.Configuration["JwtSettings:Key"];



✅ Great for development, but never store real secrets here in production.


๐Ÿ”‘ 2. Managing Secrets Securely in Development (dotnet user-secrets)


When working locally, use User Secrets, which store sensitive data outside your project directory — typically in your user profile folder.


Step 1: Enable User Secrets


Run in your project directory:


dotnet user-secrets init



This adds a unique UserSecretsId to your .csproj file.


Example:


<PropertyGroup>

  <UserSecretsId>c2a3d3a2-11b0-4b43-b9c1-d0d6c93b9f2f</UserSecretsId>

</PropertyGroup>


Step 2: Add a Secret

dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=myserver;Database=prod;User Id=sa;Password=P@ssword!"


Step 3: Use It in Code

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");



✅ Secrets are stored in:


Windows: %APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json


macOS/Linux: ~/.microsoft/usersecrets/<user_secrets_id>/secrets.json


๐Ÿ’ก User secrets are not committed to source control, keeping them safe.


☁️ 3. Storing Secrets in Environment Variables


For production (especially in Docker or cloud environments), use environment variables.


Example:


export ConnectionStrings__DefaultConnection="Server=tcp:prod-db;Database=App;User Id=admin;Password=Prod123!"



Then read it in .NET:


var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");



๐Ÿ’ก Use double underscores (__) in environment variable names to represent nested JSON paths.


Example:

JwtSettings__Key="SuperSecureKey123"


๐Ÿงฐ 4. Using Azure Key Vault (Recommended for Cloud)


For enterprise or cloud apps, store secrets in Azure Key Vault, and let .NET fetch them securely.


Step 1: Create a Key Vault


In Azure Portal or CLI:


az keyvault create --name MyAppVault --resource-group MyResourceGroup --location eastus


Step 2: Add Secrets

az keyvault secret set --vault-name MyAppVault --name "ConnectionStrings--DefaultConnection" --value "Server=..."


Step 3: Connect .NET to Key Vault


Install the package:


dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets



Then update your Program.cs:


using Azure.Identity;


var builder = WebApplication.CreateBuilder(args);

var keyVaultName = builder.Configuration["KeyVaultName"];

var uri = new Uri($"https://{keyVaultName}.vault.azure.net/");

builder.Configuration.AddAzureKeyVault(uri, new DefaultAzureCredential());



Now you can access secrets just like normal configuration values:


var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");



✅ Azure handles authentication via Managed Identity — no keys in your code.


๐Ÿงฉ 5. Protecting Configuration in Production

๐Ÿ”ธ Encrypt secrets at rest


If you must store secrets locally (e.g., on a VM), use Data Protection API (DPAPI) or a third-party encryption tool.


๐Ÿ”ธ Don’t log or display secrets


Avoid logging sensitive information in exceptions or logs.


๐Ÿ”ธ Use Managed Identities


Instead of storing credentials for Azure services, use Managed Identities to let your app authenticate automatically.


๐Ÿ”ธ Rotate secrets regularly


Use automation (e.g., Azure Key Vault rotation policies) to periodically rotate passwords, keys, and tokens.


๐Ÿง  6. Binding Configuration to Strongly Typed Classes


You can bind configuration sections directly to custom C# objects.


Example:


public class JwtSettings

{

    public string Key { get; set; }

    public string Issuer { get; set; }

}



In Program.cs:


builder.Services.Configure<JwtSettings>(

    builder.Configuration.GetSection("JwtSettings"));



In your controller or service:


public class AuthService

{

    private readonly JwtSettings _jwtSettings;

    public AuthService(IOptions<JwtSettings> jwtOptions)

    {

        _jwtSettings = jwtOptions.Value;

    }

}



✅ Benefits:


Strong typing


IntelliSense support


Centralized configuration management


๐Ÿงช 7. Combining Multiple Configuration Sources


You can mix multiple sources safely.


Example in Program.cs:


builder.Configuration

    .SetBasePath(Directory.GetCurrentDirectory())

    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)

    .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)

    .AddUserSecrets<Program>(optional: true)

    .AddEnvironmentVariables()

    .AddAzureKeyVault(new Uri($"https://{keyVaultName}.vault.azure.net/"), new DefaultAzureCredential());



๐Ÿ’ก This ensures that:


Defaults come from appsettings.json


Overrides come from secrets or Key Vault


Sensitive data never touches source control


✅ Best Practices Summary

Category Recommendation

Development Use dotnet user-secrets for local secret storage

Production Use environment variables or Azure Key Vault

Cloud Prefer Managed Identities to avoid hardcoded credentials

Security Never commit secrets to Git

Configuration Use strongly typed classes for cleaner code

Maintenance Rotate secrets and monitor access logs regularly

๐Ÿ’ฌ In Short


Managing secrets and configuration in .NET Core means separating sensitive information from your codebase, storing it securely, and using the .NET configuration system to inject it safely at runtime.


By combining tools like User Secrets, Environment Variables, and Azure Key Vault, you can keep your .NET applications both secure and scalable across all environments.

Learn Dot Net Course in Hyderabad

Read More

How to Scale Your Full Stack .NET Application on the Cloud

Introduction to Kubernetes with .NET Core

Using Docker for Full Stack .NET Development

How to Host Your .NET Core Application on AWS

Visit Our Quality Thought Institute in Hyderabad

Get Directions 

Subscribe by Email

Follow Updates Articles from This Blog via Email

No Comments

About

Search This Blog

Powered by Blogger.

Blog Archive