What are User Secrets and how to use them in ASP.NET Core

What are User Secrets and how to use them in ASP.NET Core

In one of my other posts, I talked about individual developer settings and how to work with environment variables in .NET Core projects. Environment variables are easy to use in scripts and can be made up fast. What if I tell you there is a better approach than the above, named User Secrets?

User secrets are placed inside a settings file quite similar to the one we know already named appsettings.json. By using user secrets you can achieve a structured way of handling settings and that’s what I’m going to show you more about in this article.

A quick recap from the other article to understand user secrets. I have taken a copy of the appsettings.json I had from earlier for your reference:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "localhost": "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;"
  }
}

To override ConnectionStrings:localhost on individual machines, each developer would have to add a user secret using the same name.

Configure User Secrets with secrets.json

The easiest way to open up the secrets.json file is by right-clicking your project and selecting Manage User Secrets in the menu.

Manage User Secrets

This will create a new file named secrets.json for your project. You won’t see the file inside the solution explorer as it’s saved within your roaming data. The exact path for the file is: C:\Users\<username>\AppData\Roaming\Microsoft\UserSecrets\<id> where <username> of course would be your username. <id> is a randomly generated GUID that is used when connecting the file to the project you are working on.

This GUID is stored within your csproj file for your project to reference the right secrets.json file at runtime. The great thing about storing the secrets in your local data is that it’s not submitted to source control and shared with other developers.

If you take a look inside your csproj file, you can see that a bit of markup has been added for the secret:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UserSecretsId>bba7929a-b6ac-4e55-9065-1d18d2ddf83c</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
  </ItemGroup>

</Project>

If you are not using Visual Studio for your project, you can generate a random GUID yourself and add the <UserSecretsId> property manually to the csproj file.

In the appsettings.json file above we have the connection string inside the file. Let’s override that with our user secrets. The structure is quite similar to the one we have in appsettings.json.

{
  "ConnectionStrings": {
    "localhost": "Server=myServerAddress;Database=myDataBase;User Id=christian;Password=someRandomPassword;"
  }
}

If you want to simplify it a bit more, you can do the following. What way you choose is up to you, both will work:

{
  "ConnectionStrings:localhost": "Server=myServerAddress;Database=myDataBase;User Id=christian;Password=someRandomPassword;"
}

Personally, I use the second option the most as I don’t really have that many settings I would like to override. Also, I tend to use the command line with dotnet to modify the file and that would collapse our settings anyway.

Configure user secrets using command line

You probably already know about dotnet and how you can install new packages, create migrations and update your database using code first… well it can also be used to configure user secrets – awesome! Below are a few commands to help you:

List all keys and values in secrets.json

This command will show you a complete list of keys and their values from secrets.json inside your current project. If you get an error about MSBuild that could not be found, then specify what project it’s for. using --project.

dotnet user-secrets list

OR

dotnet user-secrets list --project .\<projectName>
list all user secrets with dotnet, user secrets
List all user secrets using dotnet

Set a new user secret

This command will set a new user secret in secrets.json for a new database I just made up.

dotnet user-secrets set "ConnectionStrings:ERP" "Server=myServerAddress;Database=myDataBase;User Id=erp;Password=someRandomERPPassword;"

OR

dotnet user-secrets set "ConnectionStrings:ERP" "Server=myServerAddress;Database=myDataBase;User Id=erp;Password=someRandomERPPassword;" --project .\<projectName>
set new user secret, user secrets
Set new user secret using dotnet

Remove a user secret

This command will (as you probably already guessed) remove a connection string from secrets.json. It can remove anything, but for this demo, it will be a connection string.

dotnet user-secrets remove "ConnectionStrings:localhost"

OR

dotnet user-secrets remove "ConnectionStrings:localhost" --project .\<projectName>
Remove user secrets from secrets.json with dotnet

Now that we know how to easily configure our user secrets for an application, then it’s time to use them. ASP.NET Core will automatically pick up the configuration of secrets.json. However, if you initialize your application manually, you would have to implement them manually in the builder configuration like below in Program.cs:

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
    builder.Configuration.AddUserSecrets<Program>();
}

At line 6 above, we search the assembly that contains the type Program for an instance of Microsoft.Extensions.Configuration.UserSecrets.UserSecretsIdAttribute, which specifies a user secrets ID.

Please notice that I added this piece of code to only be running if the environment is running in development mode. You should only be using user secrets when developing and not when running in production mode.

Summary

User secrets are a great alternative to environment variables. The structure in secrets.json matches the one we already have in appsettings.json and is in my opinion a great tool to administrate secrets for each developer.

When using a popular IDE like Visual Studio there is already built-in support for JSON file formatting to help you write valid JSON the first time. A user secret is not really that secret even though the name implies it. Your “secret” settings are still located on your computer in clear text and could be read by anyone else with the right privileges on the computer.

I hope this short guide about user secrets has given you a more easy way to handle individual developer settings in a more secret way for your team. If you got any issues, questions, or suggestions, please let me know in the comments. Happy coding! 🙂

Leave a Comment

Contact

Odense, Denmark

Contact Me

Connect

Subscribe

Join my email list to receive the latest updates.