When you're developing websites and web API's using ASP.NET Core, you often have passwords, API keys, and other secrets you wish to keep away from prying eyes. Adding these secrets to a configuration file, like appsettings.json, and accidentally pushing these to a Git repository could be disastrous. For development purposes, Microsoft provides a secret manager tool that stores sensitive data in a separate secrets.json file on your development PC that is read by the default configuration builder in ASP.NET Core. As such, you can avoid placing these secrets in your configuration files and accidentally adding them to your Git repository.

Configuration in ASP.NET Core

The first thing to understand is that the default configuration builder in ASP.NET CORE reads configuration settings from a variety of sources. The configuration values are read in a particular hierarchy/order, such that if the same configuration setting is read again it replaces the setting found earlier. By default, the order is as such:

  • appsettings.json
  • appsettings.{environment}.json
  • secrets.json
  • environment variables
  • command line arguments

Therefore, an environment variable will overwrite a setting in secrets.json that overwrites a setting in appsettings.json.

Secret Manager

Secrets stored by the secret manager tool can be managed directly in Visual Studio by right-clicking the Visual Studio project file or at the command line. From the command line you need to be in the same directory as your project file and initialize the project to use secrets.

$ dotnet user-secrets init

This command adds a UserSecretsId to the project file.

<UserSecretsId>5e6f813f-e0e5-435d-a201-8031565450a3</UserSecretsId>

It also adds a directory with the same name as your UserSecretsId on your development PC. This directory contains a secrets.json file that will be used to store your secrets.

Set and List Secrets for ASP.NET Core Project

Once you have enabled secrets for your ASP.NET Core project, you can set and list secrets from the command line as well. To add a secret, you can type the following command:

$ dotnet user-secrets set "WebApiOptions:ApiKey" "12345"

This will add the secret to the secrets.json file managed by the Microsoft secret manager tool. This secret is stored in plain text on your development PC.

{
  "WebApiOptions:ApiKey": "12345"
}

You can list all the secrets for your ASP.NET Core project from the command line to view the secret API key.

$ dotnet user-secrets list

"WebApiOptions:ApiKey": "12345"

Using Secrets in ASP.NET Core Project

Using secrets in an ASP.NET Core Razor Pages website or ASP.NET Core Web API is no different than reading configuration information into your project. As mentioned earlier, when you read configuration data into your web application it is read in a particular order from a variety of sources, one of those default sources being user secrets.

Let's say I have an ASP.NET Core Razor Pages website and I wish to read the API key into my application from configuration. I configure the appsettings.json file to hold a dummy value for this API key for illustration purposes and have stored the real development API key in secrets.json using the secret manager tool. The appsettings.json file contains the following information.

{
  "WebApiOptions": {
    "SecretKey":  "dummy"
  },...
}

I wish to read this configuration data into the ASP.NET Core Razor Pages web application during startup. Let's bind it to a class and add it to the dependency injection container to make it available across the entire web application using the Options Pattern.

public class WebApiOptions
{
    public string ApiKey { get; set; }
}

In the Startup class I add it to the dependency injection container.

public void ConfigureServices(IServiceCollection services)
{
    services.AddOptions()
        .Bind(Configuration.GetSection(nameof(WebApiOptions)))
        .ValidateDataAnnotations();
    }
}

Now I can inject this information into any Razor page or service in the ASP.NET Core web application.

public class IndexModel : PageModel
{
    private readonly WebApiOptions _webApiOptions;

    public IndexModel(IOptions<WebApiOptions> webApiOptionsAccessor)
    {
        _webApiOptions = webApiOptionsAccessor.Value;
    }

    public void OnGet()
    {
        var apiKey = _webApiOptions.ApiKey;
    }
}

The variable apiKey should be 12345 if you've successfully added the secret using the secret manager tool as mentioned above. If you haven't added the secret, the value will be dummy. Again, this is because the ApiKey setting in secrets will overwrite the ApiKey setting in appsettings.json, thereby allowing you to commit this code into a Git repository with dummy data and having the real developer API key replace the dummy value when you run it locally during application development.

Azure App Services

There are a couple of things worth noting when deploying an ASP.NET Core web application to Azure App Services.

First, each app service has application settings. The easiest way to see them is in the Azure Portal. These application settings appear as environmental variables to the web application. You can add the production API Key as an application setting and it will be read in by the configuration builder and override the dummy value in appsettings.json just like we did with secrets using the secret manager tool.

Second, Azure has a service called Key Vault, which is a more secure way of storing secrets for your applications. It takes slightly more work to use Key Vault with ASP.NET Core as you will need to add it as a configuration source. However, once you configure your ASP.NET Core web application to use Key Vault, it transparently reads sensitive configuration data into your web application from Key Vault as it reads configuration data from secrets, environment variables, etc.

I'll talk more about this in later posts.

Conclusion

There are a few ideas to grasp from this tutorial. First, configuration data is read from a variety of sources during web application startup. As such, you can use this knowledge to avoid storing sensitive data and accidentally publishing it to a Git repository.

Microsoft offers a secret manager tool that allows one to store secrets (in plain text) on the local development PC and these secrets are available locally during application development. These secrets overwrite any settings in appsettings.json and appsettings.{environment}.json.

For Microsoft developers hosting their web applications on Azure App Services, you can also store your production application settings in the app service settings on Azure as well as Key Vault. Key Vault is the recommended way to store sensitive data when running production web applications in Azure.