Gray Wolf Corporation

User secrets in ASP .Net Core

User secrets are a handy way to move your sensitive application settings outside of the appsettings.json. This allows you to check in code to public or private repositories without worrying about whether database connection strings, passwords, etc are included in the checkin.

I use user secrets in this manner for posting code to a public github repository that I can use for code reviews with potential clients.

This post is a general overview of how to use user secrets. The article I referenced to put it all together can be found here.

Setting up user secrets

User secrets are stored in plain-text in json format located in the windows directory:

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

user_secrets_id is a GUID - if none exists in your UserSecrets folder, you can create with the following command:

dotnet user-secrets set "AppSettings:ConnectionString"

After finding or creating the secret folder(GUID), you need to add it to your ASP .Net Core project:

secret1

While secrets.json is a json file, it flattens any structure that may have existed in appsettings.json.

appsettings.json

{
  "AppSettings": {
    "ConnectionString": "your-connection-string"    
	}	
}

secrets.json

{
  "AppSettings:ConnectionString": "your-connection-string"
} 

This is something to keep in mind when you set your app settings in Azure or when binding the settings to a POCO as detailed below.

ASP .Net Core configuration

In Startup.cs, we need to configure the app to look for secrets if in development mode, otherwise use the app settings that will be pulled from Azure. If an appsettings.json file exists, it will be read in, but any settings will be overridden if they also exist in Azure/Environment and/or user secrets.

Startup.cs - full code HERE

private readonly IConfigurationRoot _configuration;
private readonly IHostingEnvironment _environment;
private readonly WeblogConfigurationDto _webConfiguration = new WeblogConfigurationDto();

public Startup(IConfiguration configuration, IHostingEnvironment environment)
{
	var configurationBuilder = new ConfigurationBuilder()
		.SetBasePath(environment.ContentRootPath)
		.AddJsonFile("appsettings.json", optional: true)
		.AddEnvironmentVariables();

	if (environment.IsDevelopment())
	{
		configurationBuilder.AddUserSecrets<Startup>();
	}

	_configuration = configurationBuilder.Build();
	_configuration.GetSection("AppSettings").Bind(_webConfiguration);
	_environment = environment;
}

In the above, the app gets the current directory and looks for an optional appsettings.json file. It next looks for any settings that may exist in the Environment variables. If the app is in Development mode, it checks for user secrets and loads any that may exist. The order is important, as the app will overwrite any existing setting if it exists in a later configuration.

The last configuration action is to bind the settings to a POCO, so that we can reference the POCO properties, rather than using the setting key.

public class WeblogConfigurationDto
{
	public string ConnectionString { get; set; }
}

We can then reference the POCO property, rather than the setting key.

public IServiceProvider ConfigureServices(IServiceCollection services)
{
	services.AddDbContext<GwcDbContext>(cfg =>
	{
		cfg.UseSqlServer(_webConfiguration.ConnectionString);
	});
}

To acccess the setting value by key use:

	var connectionString = _configuration["AppSettings:ConnectionString"];

Azure Environment Variables

The last piece is to configure your Azure application settings to match the flattened secret format.

secret2

An unhandled error has occurred. Reload 🗙