Configure and use User Secrets in .NET Core 2.0 Console apps in development

Managing sensitive information and secrets in config files is something we have to deal with on a daily basis. Unfortunately, this is also something that we still get wrong. In many cases, secrets spill from production to development and vice versa or we have to setup up obscure file transformations and processes to change said secrets as we move from one environment to another.

.NET Core has introduced the notion of User Secrets which we can use to store application variables outside the application folder. The file that stores the secrets ends up in one of the following locations, depending on the OS:

  • Windows: %APPDATA%\microsoft\UserSecrets\<userSecretsId>\secrets.json
  • Linux: ~/.microsoft/usersecrets/<userSecretsId>/secrets.json
  • Mac: ~/.microsoft/usersecrets/<userSecretsId>/secrets.json

The ideal service for managing user and application secrets is Azure Key Vault. I've talked about using KeyVault in the earlier posts. Multiple KeyVaults, usually one per environment, can help decouple our secrets from our applications. Unfortunately, this is not always an option, since many companies don't always allow access to Azure. So what's the next best option?

How to configure the User Secrets feature

This feature is not enabled by default so there are a few steps required in order to set it up. First, let's create a sample .NET Core project

dotnet new console {projectName}

Next, open the *.csproj file and add a few NuGet packages and the appropriate tooling to allow us to use the dotnet user-secrets commands from the command line:

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="2.0.0" />
  </ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.0" />
  </ItemGroup>

To add or remove a secret, we can use the dotnet user-secrets command:

However, at this point, attempting to add a new secret using the command line, will result to the following error message:

To resolve this, we need to add the missing settting in the *.cspoj file. Add the <UserSecretsId> tag as per the example below

<PropertyGroup>  
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <UserSecretsId>4270b588-c2ce-4c08-91bb-58aa1901134c</UserSecretsId>
  </PropertyGroup>

Trying the same dotnet user-secrets command again, should now succeed:

We can verify this by checking the designated directory where the secrets.json file should reside:

Consuming User Secrets in the Console application

For a console application to consume secrets, we can use the same Configuration setup as for all other application properties. This is the beauty of this feature. We don't need to change anything in our code other than explicitly configure the consumption of secrets. Also, since we only want to consume secrets during the development stage, I've configured a NETCORE_ENVIRONMENT variable like this:

NETCORE_ENVIRONMENT=Development

In our console application, the code for adding the user secrets in the Configuration and accessing the properties is attached below:

Summary

The only reason I put this post together is that there's no documentation that describes how to configure and consume user secrets end-to-end for .NET Core 2.0 console applications. Hopefully, you'll find this equally useful.


  • Share this post on
comments powered by Disqus