.NET User Secrets Demystified: Practical Usage and Best Practices

As developers, we often need to work with sensitive information in our applications. However, hardcoding these secrets or storing them in plaintext configuration files is a recipe for disaster. It's all too easy for these secrets to end up in version control systems, exposing them to unauthorized parties.

This is where the .NET User Secrets feature comes to the rescue. In this article, we'll dive deep into how to use dotnet user-secrets to securely manage your application's sensitive information during development.

Understanding User Secrets in .NET

User Secrets in .NET is a secure way to store sensitive information for development purposes. It's designed to keep your secrets out of your project tree, ensuring they don't accidentally get committed to source control. Instead, secrets are stored in a separate location on your development machine, making them accessible to your application during development while keeping them safe from prying eyes.

Manager User Secrets

Let's walk through the process of setting up and using User Secrets in your .NET project.

First, ensure you have the .NET SDK installed on your machine. The User Secrets tool is included with the SDK, so no additional installation is required.

To start using User Secrets, navigate to your project directory in the terminal and run:

dotnet user-secrets init

This command initializes the User Secrets for your project. It adds a UserSecretsId element to your project file, which looks something like this:

<PropertyGroup>
  ...
  <UserSecretsId>ea9bd47b-ceb4-4eba-89d4-22c9277c7b4e</UserSecretsId>
</PropertyGroup>

Now that we've initialized User Secrets, let's add a secret. For example, to add an API key, you would use:

dotnet user-secrets set "ApiKey" "my-secret-api-key"

This command adds the secret "ApiKey" with the value "my-secret-api-key" to your User Secrets store with the successfull message : Successfully saved ApiKey = my-secret-api-key to the secret store.

To view all the secrets you've set for your project, use:

dotnet user-secrets list

This command will display all the secrets associated with your project, like this:

ApiKey = my-secret-api-key

You can also manage your secrets by removing or cleaning them:

dotnet user-secrets remove "Movies:ConnectionString"
dotnet user-secrets clear

User Secrets For Local Development

User Secrets are stored outside of your project directory to prevent accidental commits to source control. The storage location depends on your operating system:

  • Windows: %APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
  • macOS/Linux: ~/.microsoft/usersecrets/<user_secrets_id>/secrets.json

The <user_secrets_id> is the GUID that was added to your project file when you initialized User Secrets.

In our case, we have a secrets.json file inside the folder related to our UserSecretsId named ea9bd47b-ceb4-4eba-89d4-22c9277c7b4e.

{
  "ApiKey": "my-secret-api-key"
}

While User Secrets are a powerful tool, they have some limitations:

  • They're not encrypted, just stored in a separate location.
  • They're machine-specific, which can complicate team development.
  • They're not suitable for production environments.

For production, consider using more robust solutions like Azure Key Vault or AWS Secrets

Use is automatic for ASP.NET applications when the EnvironmentName is Development, so it can be accessed like any other configuration variable in an appsettings.json file.

This can easily be verified by looking inside the WebApplicationBuilder class with the ApplyDefaultAppConfigurationSlim method called in the constructor.

private static void ApplyDefaultAppConfigurationSlim(IHostEnvironment env, ConfigurationManager configuration, string[]? args)
{
    ...
    configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: reloadOnChange)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: reloadOnChange);

    if (env.IsDevelopment() && env.ApplicationName is { Length: > 0 })
    {
        try
        {
            var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
            configuration.AddUserSecrets(appAssembly, optional: true, reloadOnChange: reloadOnChange);
        }
        catch (FileNotFoundException)
        {
            // The assembly cannot be found, so just skip it.
        }
    }

    configuration.AddEnvironmentVariables();
    ...
}

For other types of applications, you need to add the Microsoft.Extensions.Configuration.UserSecrets library and use the AddUserSecrets() extension to the ConfigurationManager class manually to access it, respecting the development environment so as not to deliver in production:

// Example to AddUserSecrets manually
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddUserSecrets<Program>();

Best Practices for Using User Secrets

While User Secrets provide a secure way to manage sensitive information during development, it's important to follow best practices:

  • Never use User Secrets in production. They are meant for development environments only.
  • Regularly rotate your secrets, even during development.
  • Use descriptive names for your secrets to easily identify their purpose.
  • Limit access to the secrets file on your development machine.

User Secrets isn't the only way to manage sensitive information. Let's compare it with some alternatives:

  • Environment Variables: These are system-wide and can be easier to set up, but they're not project-specific like User Secrets.
  • Azure Key Vault: This is a cloud-based secure storage system, ideal for production environments but might be overkill for local development.
  • Configuration Files: While easy to use, these risk exposing secrets if accidentally committed to source control.

User Secrets strikes a balance between security and ease of use for development environments.

Conclusion

User Secrets in .NET provide a secure and convenient way to manage sensitive information during development. By keeping your secrets out of your source code and configuration files, you significantly reduce the risk of accidental exposure. Remember, User Secrets are a development tool - always use appropriate secret management solutions in your production environments.

Mastering User Secrets is an essential skill for any .NET developer committed to writing secure applications. By following the practices outlined in this article, you'll be well on your way to more secure and manageable .NET development.

To go further:

Safe storage of app secrets in development in ASP.NET Core
Learn how to store and retrieve sensitive information during the development of an ASP.NET Core app.

Have a goat day 🐐