In software development, secret management refers to securely storing and accessing sensitive data like passwords, API keys, and connection strings. .NET Core provides tools like secrets.json
and Azure Key Vault for developers to securely manage these secrets without hardcoding them into their applications.
Why is it essential? Hardcoding secrets in source code or configuration files (like appsettings.json
) that are tracked in source control can expose sensitive information. With secret management, we can separate sensitive data from application code.
This blog explains how .NET Core provides secret management capabilities to securely handle such information using tools like user secrets (for local development) and Azure Key Vault (for production-grade security). You’ll learn when to use each tool and how to seamlessly access these secrets in your applications.
Why Use secrets.json
When We Have appsettings.json
?
Though appsettings.json
holds configuration data, it is meant for non-sensitive, application-specific settings, such as API base URLs, default settings, or application modes.
Key reasons for using secrets.json
for sensitive data:
- Security: Sensitive information in
secrets.json
is not stored in source control, protecting it from unauthorized access. - Environment-Specific: Each developer can have unique secrets on their local machine without affecting others.
- Overriding Behavior: Secrets in
secrets.json
override values inappsettings.json
during development, making it easy to test local configurations.
Secret Management Using secrets.json
in .NET Core
The secrets.json
file stores secrets locally in a secure, file-based store specific to each user. Here’s how to manage secrets with secrets.json
.
Step-by-Step Example:
Create a New .NET Core Project:
- Open Visual Studio and create a new ASP.NET Core Web Application.
- Select Empty or Web API as the project template and set a name for your project.
Enable User Secrets:
· Right-click your project in Solution Explorer.
· Select Manage User Secrets. Visual Studio will create-
- a unique
UserSecretsId
in your.csproj
file. - a
secrets.json
blank file outside the project directory in%APPDATA%\Microsoft\UserSecrets\your-app-guid\secrets.json
(on Windows).
<PropertyGroup>
<UserSecretsId>your-app-guid</UserSecretsId>
</PropertyGroup>
Add Secrets to secrets.json
:
- In Visual Studio, right-click the project in Solution Explorer, then select Manage User Secrets. This action opens
secrets.json
file which is linked to your project.
{
"ConnectionStrings": {
"DefaultConnection": "Server=myServer;Database=myDB;User=myUser;Password=myPassword;"
},
"ApiKeys": {
"GoogleMaps": "YOUR_GOOGLE_MAPS_API_KEY"
}
}
Access Secrets in Code: To access secrets from secrets.json
, inject IConfiguration
directly into the HomeController
. In this example, we use HomeController
to retrieve secrets, but you could also inject IConfiguration
into any other class in your project, such as a service or repository class, depending on your project’s structure and requirements.
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
public class HomeController : Controller
{
private readonly IConfiguration _configuration;
public HomeController(IConfiguration configuration)
{
_configuration = configuration;
}
public IActionResult Index()
{
var connectionString = _configuration["ConnectionStrings:DefaultConnection"];
var googleMapsKey = _configuration["ApiKeys:GoogleMaps"];
return Content($"Database: {connectionString}, Google Maps Key: {googleMapsKey}");
}
}
Run the Application:
- Start the project to see if secrets are loaded correctly without exposing sensitive values directly in code or
appsettings.json
.
Secret Management Using Azure Key Vault in .NET Core
Azure Key Vault is a secure cloud storage solution that centralizes secret management and allows you to securely store secrets, keys, and certificates. It’s recommended for production as it provides higher security and access management.
- Setting Up Azure Key Vault
To use Key Vault, you need an Azure account. Here’s how to integrate it into your .NET Core application:
- Create an Azure Key Vault in the Azure portal.
- Add Secrets: Navigate to the Key Vault in Azure, select Secrets, and create secrets like
ConnectionStrings--DefaultConnection
orApiKeys--ThirdPartyService
. - Set Up Authentication: You can use
DefaultAzureCredential
for local development and deployment environments if you've configured Azure credentials in your environment or for Managed Identity in Azure services.
- Configure Key Vault in Program.cs
Install the Azure.Extensions.AspNetCore.Configuration.Secrets
NuGet package:
dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets
In Program.cs
, add Key Vault to the configuration:
using Azure.Identity;
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddAzureKeyVault(
new Uri("https://<Your-KeyVault-Name>.vault.azure.net/"),
new DefaultAzureCredential());
var app = builder.Build();
Here, replace <YourVaultName>
with your actual Key Vault name.
- Accessing Secrets from Key Vault in Code
Access secrets using IConfiguration
the same way as with user secrets:
public class MyService
{
private readonly IConfiguration _configuration;
public MyService(IConfiguration configuration)
{
_configuration = configuration;
}
public string GetApiKey()
{
return _configuration["ApiKeys:ThirdPartyService"];
}
}
Environment-Specific Secret Management
.NET Core supports environment-specific configurations, allowing the application to load different secrets for Development, Staging, or Production.
Managing Secrets by Environment:
- Development: Use
secrets.json
for local, non-production secrets. This allows developers to have their own environment-specific configurations. - Staging and Production: Use Azure Key Vault to secure secrets centrally, as they are shared by multiple developers.
Example:
To set up environment-specific configurations, you can conditionally add sources in Program.cs
based on the environment:
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
builder.Configuration.AddUserSecrets<Program>();
}
else
{
builder.Configuration.AddAzureKeyVault(new Uri("https://<YourVaultName>.vault.azure.net/"), new DefaultAzureCredential());
}
Best Practices for Secret Management
- Avoid Hardcoding Secrets: Never hardcode sensitive information directly in code or in
appsettings.json
. - Limit Access to Secrets: Use role-based access in Azure Key Vault to limit who can access production secrets.
- Secure Local Secrets: Use
secrets.json
for local development only and avoid adding sensitive information to shared configuration files. - Rotate Secrets Regularly: Ensure periodic rotation of secrets, especially for high-security applications.
- Audit Secret Access: Use Azure Key Vault logs to monitor who accesses secrets, especially in production.
Secret management in .NET Core, through User Secrets and Azure Key Vault, provides a robust way to protect sensitive information from exposure. By using User Secrets for development and Azure Key Vault for production, .NET Core developers can ensure secure management of sensitive configurations while maintaining easy access in their applications.
For real-life applications, keep local settings in appsettings.json
or secrets.json
and use Azure Key Vault for production to balance convenience and security effectively.
Still need appsettings.json
?
if you use secrets.json
, you still typically need appsettings.json
. Here’s how they work together:
Purpose:
appsettings.json
holds non-sensitive, shared configuration data for your application, such as application settings, logging configurations, and other general information.secrets.json
, on the other hand, is specifically for sensitive data (e.g., connection strings, API keys) that you don’t want in source control.
Complementary Use:
appsettings.json
is checked into source control, so it’s accessible to everyone working on the project.secrets.json
is excluded from source control and is stored only on your local machine, allowing you to store local, sensitive values securely during development.
Configuration Hierarchy:
- When both
appsettings.json
andsecrets.json
are used, .NET Core merges configurations, withsecrets.json
taking priority for any overlapping keys. This means secrets insecrets.json
will override values inappsettings.json
.
For instance, you might keep a placeholder in appsettings.json
:
"ConnectionStrings": {
"DefaultConnection": "YourConnectionStringPlaceholder"
}
And then define the actual connection string in secrets.json
:
"ConnectionStrings": {
"DefaultConnection": "Server=myServer;Database=myDB;User Id=myUser;Password=myPassword;"
}
This setup ensures that the sensitive values in secrets.json
override the placeholders in appsettings.json
and that sensitive information is kept secure during development.
If you found this blog helpful, please share it with your peers and colleagues. Don't forget to subscribe to our YouTube channel(Visit Codexoom on YouTube) for more tutorials on ASP.NET Core and professional software development tips!
Thank you for joining us, and as always, happy coding! Until next time, stay curious and keep building amazing things. Take care!