This document explains how to manage sensitive data for an ASP.NET Core app on a development machine. Never store passwords or other sensitive data in source code. Production secrets shouldn’t be used for development or test. Secrets shouldn’t be deployed with the app. Instead, production secrets should be accessed through a controlled means like environment variables or Azure Key Vault. You can store and protect Azure test and production secrets with the Azure Key Vault configuration provider.
Environment variables are generally stored in plain, unencrypted text. If the machine or process is compromised, environment variables can be accessed by untrusted parties. Additional measures to prevent disclosure of user secrets may be required.
Secret Manager Tool
The Secret Manager tool stores sensitive data during the development of an ASP.NET Core project. In this context, a piece of sensitive data is an app secret. App secrets are stored in a separate location from the project tree. The app secrets are associated with a specific project or shared across several projects. The app secrets aren’t checked into source control.
Warning: The Secret Manager tool doesn’t encrypt the stored secrets and shouldn’t be treated as a trusted store. It’s for development purposes only. The keys and values are stored in a JSON configuration file in the user profile directory.
How the Secret Manager tool works
The Secret Manager tool hides implementation details, such as where and how the values are stored. You can use the tool without knowing these implementation details. The values are stored in a JSON file in the local machine’s user profile folder:
File system path:
%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
C:\Users\user01\AppData\Roaming\Microsoft\UserSecrets\e13a4f3c-0111-4fcc-bba1-11d7e67a1b6d\secrets.json
In the preceding file paths, replace <user_secrets_id>
with the UserSecretsId
value specified in the project file.
Don’t write code that depends on the location or format of data saved with the Secret Manager tool. These implementation details may change. For example, the secret values aren’t encrypted, but could be in the future.
Enable secret storage
The Secret Manager tool operates on project-specific configuration settings stored in your user profile.
The Secret Manager tool includes an init
command in .NET Core SDK 3.0.100 or later. To use user secrets, run the following command in the project directory:
.NET CLI
Note: run the following in “Developer command Prompt” tool after navigation to the project folder.
C:\MyApp01\Client>dotnet user-secrets init
C:\MyApp01\Client>dotnet user-secrets init --project xxxxxxxx
The preceding command adds a UserSecretsId
element within a PropertyGroup
of the project file. By default, the inner text of UserSecretsId
is a GUID. The inner text is arbitrary, but is unique to the project.
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<UserSecretsId>79a3edd0-2092-40a2-a04d-dcb46d5ca9ed</UserSecretsId>
</PropertyGroup>
In Visual Studio, right-click the project in Solution Explorer, and select Manage User Secrets from the context menu. This gesture adds a UserSecretsId
element, populated with a GUID, to the project file.
Set a secret
Define an app secret consisting of a key and its value. The secret is associated with the project’s UserSecretsId
value. For example, run the following command from the directory in which the project file exists:.NET CLICopy
dotnet user-secrets set "Movies:ServiceApiKey" "12345" --project "C:\apps\WebApp1\src\WebApp1"
In the preceding example, the colon denotes that Movies
is an object literal with a ServiceApiKey
property.
secrets.json
{
"Movies:ServiceApiKey": "12345"
}
Access a secret
To access a secret, complete the following steps:
Note: For Azure App Service deployment, add entry to application settings in configuration section on Azure Portal.
Register the user secrets configuration source
The user secrets configuration provider registers the appropriate configuration source with the .NET Configuration API.
The user secrets configuration source is automatically added in Development mode when the project calls CreateDefaultBuilder. CreateDefaultBuilder
calls AddUserSecrets when the EnvironmentName is Development:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
When CreateDefaultBuilder
isn’t called, add the user secrets configuration source explicitly by calling AddUserSecrets in ConfigureAppConfiguration. Call AddUserSecrets
only when the app runs in the Development environment, as shown in the following example:
public class Program
{
public static void Main(string[] args)
{
var host = new HostBuilder()
.ConfigureAppConfiguration((hostContext, builder) =>
{
// Add other providers for JSON, etc.
if (hostContext.HostingEnvironment.IsDevelopment())
{
builder.AddUserSecrets<Program>();
}
})
.Build();
host.Run();
}
}
Read the secret via the Configuration API
If the user secrets configuration source is registered, the .NET Configuration API can read the secrets. Constructor injection can be used to gain access to the .NET Configuration API. Consider the following examples of reading the Movies:ServiceApiKey
key:
Startup class:
public class Startup
{
private string _moviesApiKey = null;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
_moviesApiKey = Configuration["Movies:ServiceApiKey"];
}
public void Configure(IApplicationBuilder app)
{
app.Run(async (context) =>
{
var result = string.IsNullOrEmpty(_moviesApiKey) ? "Null" : "Not Null";
await context.Response.WriteAsync($"Secret is {result}");
});
}
}
Razor Pages page model:
public class IndexModel : PageModel
{
private readonly IConfiguration _config;
public IndexModel(IConfiguration config)
{
_config = config;
}
public void OnGet()
{
var moviesApiKey = _config["Movies:ServiceApiKey"];
// call Movies service with the API key
}
}
For more information, see Access configuration in Startup and Access configuration in Razor Pages.
Sources:
https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows
Comments