DEV Community

Cover image for You don't know how to keep your secrets.
Serhii Korol
Serhii Korol

Posted on

You don't know how to keep your secrets.

I frequently faced that people keep passwords and tokens in the wrong way. Most people keep it in appsettings file. It's wrong. These files are only for application settings like environments, flags, and URLs. I will show you the best practices for keeping sensitive information.

Let's create a simple console application:

dotnet new console -n SecretsSample
Enter fullscreen mode Exit fullscreen mode

You also need to install the required packages.

<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0-rc.2.23479.6" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0-rc.2.23479.6" />
Enter fullscreen mode Exit fullscreen mode

After that, add the base class and method for running the application.

internal static class Program
{
    static void Main(string[] args)
    {
            var environmentName = "Development";
            var host = CreateHostBuilder(args, environmentName).Build();
    }
}
Enter fullscreen mode Exit fullscreen mode

And let's configure our host, and I'll explain what I'm doing.

internal static class Program
    {
        static void Main(string[] args)
        {
            var environmentName = "Development";
            var host = CreateHostBuilder(args, environmentName).Build();
            Console.WriteLine("Application is running...");
            host.Run();
        }

        private static IHostBuilder CreateHostBuilder(string[] args, string environmentName) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    ApplyDefaultAppConfiguration(hostingContext, config, args, environmentName);
                });

        private static void ApplyDefaultAppConfiguration(HostBuilderContext hostingContext, IConfigurationBuilder appConfigBuilder, string[]? args, string environmentName)
        {
            IHostEnvironment env = hostingContext.HostingEnvironment;
            env.EnvironmentName = environmentName;

            bool reloadOnChange = GetReloadConfigOnChangeValue(hostingContext);
            appConfigBuilder.AddJsonFile("appsettings.json", optional: true, reloadOnChange: reloadOnChange)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: reloadOnChange);
            if (env.IsDevelopment() && env.ApplicationName is { Length: > 0 })
            {
                var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
                appConfigBuilder.AddUserSecrets(appAssembly, optional: true, reloadOnChange: reloadOnChange);
            }
            appConfigBuilder.AddEnvironmentVariables();
            if (args is { Length: > 0 })
            {
                appConfigBuilder.AddCommandLine(args);
            }
        }

        static bool GetReloadConfigOnChangeValue(HostBuilderContext hostingContext) => hostingContext.Configuration.GetValue("hostBuilder:reloadConfigOnChange", defaultValue: true);
    }
Enter fullscreen mode Exit fullscreen mode

I set the environment and created a host. Pay attention to the ApplyDefaultAppConfiguration method. It parses all settings, and if the environment is Development, we'll parse secrets.
Let's create a secrets file, and you need to run this command in a command line:

dotnet user-secrets init
Enter fullscreen mode Exit fullscreen mode

After that, it will be created the secrets.json file. Which was saved in .microsoft/usersecrets/[user secrets id] folder. You'll get your own ID that also was added to the project:

<PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net7.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <UserSecretsId>fe9bac73-2f74-4fc5-b490-38a62750525b</UserSecretsId>
    </PropertyGroup>
Enter fullscreen mode Exit fullscreen mode

With this ID, the application can read secrets. Let's add something to it.

{
  "Hello": "World!"
}
Enter fullscreen mode Exit fullscreen mode

To check it, let's add more code to the main method.

var config = host.Services.GetService<IConfiguration>();
            var mySettingValue = config?["Hello"];
            Console.WriteLine(string.IsNullOrEmpty(mySettingValue)
                ? "This value only for Development mode"
                : $"Hello, {mySettingValue}");
Enter fullscreen mode Exit fullscreen mode

If you run it, you'll see the message in the console.

console 1

Suppose we change the environment name to Production. We'll get a different message.

console 2

For the ending, I want to add the secrets.json file is not a part of the project, and you can't push it accidentally to git. However, you must pass this file if you want others to work on the project.

See you on the following week. Happy coding!
Source code: LINK

Buy Me A Beer

Top comments (0)