ASP.NET Core Secret Manager

ASP.NET Core Secret Manager, i.e., secrets.json file

In this article, I will discuss ASP.NET Core Secret Manager, i.e., secrets.json file. Please read our previous article discussing How to Integrate Facebook External Authentication in ASP.NET Core MVC.

Why We Should Not Store Secrets in Configuration Files in ASP.NET Core?

Storing secrets, like database connection strings, API keys, or encryption keys, directly in configuration files in ASP.NET Core is not recommended for several reasons:

  • Security Risks: Configuration files, such as appsettings.json in ASP.NET Core, are often part of the source code repository. Storing secrets in these files makes them vulnerable to exposure, especially if the repository is public or shared among team members. Anyone accessing the repository can view these secrets, increasing the risk of security breaches.
  • Accidental Exposure: When configuration files are updated or shared, there’s a risk of accidentally exposing secrets. For example, sensitive information could be unintentionally leaked when sharing code for troubleshooting or collaboration.
  • Environment-Specific Configuration: Storing secrets in configuration files doesn’t account for different environments (development, staging, production). Each environment typically requires different secrets, and managing these variations within the codebase is not practical.
  • Compliance and Best Practices: Many compliance frameworks (such as PCI DSS for payment processing) require strict handling of sensitive information. Storing secrets in configuration files often violates these regulations.

To overcome these risks, it’s recommended to use secure secrets management practices. In ASP.NET Core, this can be achieved by:

  • Using Secret Manager Tool: For development, ASP.NET Core provides a Secret Manager tool that stores secrets in a separate location from the project tree.
  • Environment Variables: Storing secrets in environment variables is another common practice. These are separate from the application’s codebase and can be managed independently.
  • Secure Deployment Practices: Implementing Continuous Integration and Continuous Deployment (CI/CD) pipelines with secure handling of secrets, ensuring they are not exposed during deployment.

Note: I will discuss using Secret Manager to store sensitive information in the development environment in this article. The most important point you must remember is that the Secret Manager will only work in the Development Environment, not in Production or Staging Environments.

What is ASP.NET Core Secret Manager?

ASP.NET Core Secret Manager is a feature Microsoft provides for managing and storing sensitive data while developing ASP.NET Core Applications. It is useful for avoiding the storage of secrets like database passwords, API keys, External Provider’s API IDs and Secrets, or other sensitive information in the code or source control. Here’s a brief overview of its key aspects:

  • Purpose: The Secret Manager is intended for development purposes only. It is not recommended to use it for storing secrets in production environments. This is important because it prevents you from storing sensitive information like database connection strings, API keys, External Pr0viders API ID, and Secrets or other credentials in your code or configuration files, which can be a security risk if they are shared or stored in source control.
  • How it Works: The Secret Manager stores the application-sensitive data in a separate location on your machine. These secrets are stored in your machine’s system-protected user profile folder, isolated from the project tree.
  • Accessing Secrets: Secrets can be accessed in an ASP.NET Core application through configuration APIs. The application doesn’t need to know where the secrets are stored.
  • Limitation: The stored secrets are not encrypted, and the tool does not provide protection against malicious attacks and relies on the security of the user profile folder on the developer’s machine.
How Do We Create Secret Manager in ASP.NET Core?

To add this file to your project, right-click the project name in Solution Explorer in Visual Studio and select Manage User Secrets from the context menu, as shown in the image below.

How Do We Create Secret Manager in ASP.NET Core?

This will add a secrets.json file, as shown in the below image. The structure of this file is similar to appSettings.json. The important point to remember is that this file is not part of the project folder. It is located outside of the project folder. To find the secrets.json file location, right-click on the secrets.json file and select the Open Containing Folder option, as shown in the below image.

ASP.NET Core Secret Manager, i.e., secrets.json file

This will open the following:

ASP.NET Core Secret Manager, i.e., secrets.json file

The complete path is: C:\Users\Pranaya\AppData\Roaming\Microsoft\UserSecrets\e9c1faec-62e6-4e7b-9d63-0967944a042e

So, we can say the path for the secrets.json file is: C:\Users\{UserName}\AppData\Roaming\Microsoft\UserSecrets\{ID}

Here,

  • {UserName} is the Windows User Name you use to log into the computer; in my case, it is Pranaya.
  • {ID} is a GUID (Globally Unique Identifier); in my case, it is e9c1faec-62e6-4e7b-9d63-0967944a042e.

On a single computer or your machine, you may have multiple ASP.NET Core Projects and a secrets.json file for each project. This GUID links a given secrets.json file to a given ASP.NET Core project.

How Does the ASP.NET Core Project link with this Secret File?

To establish the link between the ASP.NET Core Project and the secrets.json file, ASP.NET Core adds the following UserSecretsId node in the .csproj file. To see this, right-click on your project and click on the Edit Project File option from the context menu. The value of UserSecretsId is nothing but the GUID value of the secrets.json file.

How Does the ASP.NET Core Project link with this Secret File?

Using Secret Manager to Store Sensitive Data:

Let us see how to use Secret Manager to store sensitive information about our application, like database connection string, Facebook, Google, Microsoft App ID, and Secret. So, modify the secrets.json file as follows:

{
  "ConnectionStrings:SQLServerIdentityConnection": "[Your Database Connection String]",
  "Facebook:AppId": "[Your Facebook Client ID]",
  "Facebook:AppSecret": "[Your Facebook Client Secret]",

  "Microsoft:AppId": "[Your Microsoft Client ID]",
  "Microsoft:AppSecret": "[Your Microsoft Client Secret]",

  "Google:AppId": "[Your Google Client ID]",
  "Google:AppSecret": "[Your Google Client Secret]"
}

Next, we need to see how to fetch the data from the secrets.json file. Using the same ConfigurationManager, we can read the data from the secrets.json file.

Reading the Connection String:

Please observe the following code. The following code will fetch the connection string from the secrets.json file if and only if the environment is Development.

var connectionString = builder.Configuration["ConnectionStrings:SQLServerIdentityConnection"] ?? throw new InvalidOperationException("Connection string 'SQLServerIdentityConnection' not found.");
Reading the External API ID and Secrets:
var GoogleClientId = builder.Configuration["Google:AppId"];
var GoogleClientSecret = builder.Configuration["Google:AppSecret"];

var MicrosoftClientId = builder.Configuration["Microsoft:AppId"];
var MicrosoftClientSecret = builder.Configuration["Microsoft:AppSecret"];

var FacebookClientId = builder.Configuration["Facebook:AppId"];
var FacebookClientSecret = builder.Configuration["Facebook:AppSecret"];

builder.Services.AddAuthentication()
.AddGoogle(options =>
{
    options.ClientId = GoogleClientId;
    options.ClientSecret = GoogleClientSecret;
    // You can set other options as needed.
})
.AddMicrosoftAccount(microsoftOptions =>
{
    microsoftOptions.ClientId = MicrosoftClientId;
    microsoftOptions.ClientSecret = MicrosoftClientSecret;
})
.AddFacebook(facebookOptions =>
{
    facebookOptions.ClientId = FacebookClientId;
    facebookOptions.ClientSecret = FacebookClientSecret;
});
Setting the Environment to Development:

Secret Manager isn’t for staging or production servers and should only be used in the development environment. Always use environment variables, Azure Key Vault, or 3rd party production secret management system for production. So, please set the environment to Development before running the application.

Once you set the Environment to Development, run the application, which should work as expected. But if you set the environment to Staging or Production, it will not work, and in that case, if you want to store the same in the appSettings.json file, then you need to modify the appSettings.json file as follows:

{
  "ConnectionStrings": {
    "SQLServerIdentityConnection": "[Your Database Connection String]"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
   "Facebook:AppId": "[Your Facebook Client ID]",
  "Facebook:AppSecret": "[Your Facebook Client Secret]",

  "Microsoft:AppId": "[Your Microsoft Client ID]",
  "Microsoft:AppSecret": "[Your Microsoft Client Secret]",

  "Google:AppId": "[Your Google Client ID]",
  "Google:AppSecret": "[Your Google Client Secret]"
}

Configuration File Reading Order in ASP.NET Core

In ASP.NET Core, the configuration system is very flexible, allowing you to read configuration settings from various sources like JSON files, environment variables, command-line arguments, etc. The order in which these configurations are read and applied is important, as later configurations will override earlier ones. Here’s the typical order in which configurations are read in an ASP.NET Core application:

  • appsettings.json: This is the standard configuration file in JSON format. It’s read first and provides a basic configuration structure.
  • appsettings.{Environment}.json: Environment-specific settings are placed in these files. {Environment} is typically set to Development, Staging, or Production values. This file is read after appsettings.json, and its settings will override those in appsettings.json for the corresponding environment.
  • User Secrets: This is used in development mode (when the ASPNETCORE_ENVIRONMENT is set to Development). User secrets are stored outside the project and not checked into source control. The settings in this file override those in appsettings.json and appsettings.{Environment}.json.
  • Environment Variables: Configuration settings in environment variables are read next. These are key-value pairs set in the environment of the system running the application. They can be used to override settings for all environments and are particularly useful for managing settings in production.
  • Command-line Arguments: Configuration settings can be provided via command-line arguments when the application starts. These will override all the previous settings.
When to Use ASP.NET Core Secret Manager?

The ASP.NET Core Secret Manager is useful in scenarios where you need to store sensitive data during the development phase of a project. Here are some key situations when you should consider using it:

  • Local Development: When developing locally, you might need to use sensitive information like database connection strings, API keys, or service credentials. Instead of hardcoding these values in your configuration files, you can use Secret Manager to store them safely.
  • Avoiding Hardcoded Secrets: Hardcoding secrets in your code or configuration files (like appsettings.json) is not secure, especially if the code is stored in a source control repository. Secret Manager helps to keep these secrets out of your codebase.
  • Environment-Specific Secrets: When different developers or different environments (like development, staging, and production) require different sets of secrets, Secret Manager can be used to manage these variations without changing the code.
  • Integration with Configuration API: ASP.NET Core’s configuration system can seamlessly integrate with Secret Manager, allowing you to retrieve secrets like other configuration settings.
  • Testing Purposes: During testing, especially automated testing, you might need to use different secrets without exposing them. Secret Manager can be used to store these secrets locally.
  • Temporary Secret Storage: If you need a place to store secrets temporarily during development before setting up a more permanent and secure solution for production (like Azure Key Vault or AWS Secrets Manager), Secret Manager is a good choice.

Note: It’s important to remember that the Secret Manager tool is intended for development purposes only. It’s not suitable for managing secrets in production environments. For production, you should consider more secure methods like environment variables, Azure Key Vault, or other secure storage mechanisms.

In the next article, I will discuss Configuring Email Service in ASP.NET Core Identity. In this article, I explain ASP.NET Core Secret Manager. I hope you enjoy this article, ASP.NET Core Secret Manager.

Leave a Reply

Your email address will not be published. Required fields are marked *