.NET User Secrets — Detailed Explanation
1. What is .NET User Secrets?
.NET User Secrets is a feature in ASP.NET Core used to store sensitive configuration values outside your project folder during local development.
Examples of sensitive values:
- Database connection strings
- API keys
- JWT secret keys
- SMTP passwords
- Third-party service credentials
Instead of writing a password directly in:
appsettings.json
you store it separately in:
User Secrets
Your application can still access the value through the normal ASP.NET Core IConfiguration system.
2. Why do we need User Secrets?
Suppose your appsettings.json contains:
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=PortfolioDb;User Id=sa;Password=MyPassword123;"
}
}
If you commit this file to Git:
Developer
↓
Git Commit
↓
GitHub / Azure DevOps
↓
Password exposed
This is a security risk.
Instead:
appsettings.json
↓
Non-sensitive configuration
User Secrets
↓
Passwords
Connection Strings
API Keys
JWT Secrets
User Secrets are stored outside the project, so they are not accidentally committed along with the source code.
3. Where are User Secrets stored?
On Windows, they are normally stored under:
%APPDATA%\Microsoft\UserSecrets\<UserSecretsId>\secrets.json
For example:
C:\Users\admin\AppData\Roaming\Microsoft\UserSecrets\
45fd12c1-xxxx-xxxx-xxxx\
secrets.json
The file may look like:
{
"ConnectionStrings:DefaultConnection":
"Server=localhost;Database=PortfolioDb;User Id=sa;Password=MyPassword123;"
}
Important
User Secrets are:
- Outside your project
- Not automatically committed to Git
- Associated with a
UserSecretsId - Intended for development only
- Not encrypted
So User Secrets should not be considered a production secret-management system.
4. How to implement User Secrets
Assume your project is:
Portfolio.Api
├── Portfolio.Api.csproj
├── Program.cs
├── appsettings.json
└── appsettings.Development.json
Open Command Prompt/Terminal in the folder containing:
Portfolio.Api.csproj
For example:
cd /d D:\Projects\Portfolio\Portfolio.Api
Check:
dir *.csproj
You should see:
Portfolio.Api.csproj
5. Initialize User Secrets
Run:
dotnet user-secrets init
This modifies your .csproj.
Before:
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
After initialization:
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<UserSecretsId>
12345678-abcd-1234-abcd-123456789abc
</UserSecretsId>
</PropertyGroup>
The important part is:
<UserSecretsId>...</UserSecretsId>
This ID connects your project with the appropriate local secrets store.
6. Set a User Secret
Now store your connection string:
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=PortfolioDb;User Id=sa;Password=MyPassword123;"
You should receive something similar to:
Successfully saved ConnectionStrings:DefaultConnection
7. Store other secrets
JWT Secret
dotnet user-secrets set "JwtSettings:Secret" "MyVerySecretJwtKey123456789"
API Key
dotnet user-secrets set "ApiSettings:ApiKey" "ABC123XYZ"
SMTP Password
dotnet user-secrets set "EmailSettings:Password" "MyEmailPassword"
Your secrets could conceptually look like:
{
"ConnectionStrings:DefaultConnection": "Server=localhost;Database=PortfolioDb;...",
"JwtSettings:Secret": "MyVerySecretJwtKey123456789",
"ApiSettings:ApiKey": "ABC123XYZ",
"EmailSettings:Password": "MyEmailPassword"
}
8. How to read User Secrets in ASP.NET Core
You don't need special code to read each User Secret.
ASP.NET Core integrates User Secrets into its configuration system for the Development environment for the usual web-app builder setup.
For example:
var builder = WebApplication.CreateBuilder(args);
Then:
var connectionString =
builder.Configuration.GetConnectionString("DefaultConnection");
The application can retrieve the connection string regardless of whether the effective value came from appsettings.json, User Secrets, or another configured provider.
9. Example with Entity Framework Core
Install the appropriate EF Core SQL Server provider if it isn't already installed:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
Store the connection string:
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=PortfolioDb;Trusted_Connection=True;TrustServerCertificate=True;"
Then:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")));
Notice that EF Core doesn't need to know that the connection string came from User Secrets.
10. Configuration Priority
This is very important for interviews.
ASP.NET Core configuration combines multiple configuration providers.
In the standard setup, think of the relevant precedence approximately as:
appsettings.json
↓
appsettings.Development.json
↓
User Secrets
↓
Environment Variables
↓
Command-line arguments
Later/higher-priority configuration overrides earlier values when the same key exists.
For example:
appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "APPSETTINGS_VALUE"
}
}
User Secrets
ConnectionStrings:DefaultConnection
= USER_SECRET_VALUE
Environment Variable
ConnectionStrings__DefaultConnection
= ENVIRONMENT_VALUE
The effective value would be:
ENVIRONMENT_VALUE
because the environment variable has higher precedence than User Secrets in the default configuration order.
11. View all User Secrets
Run:
dotnet user-secrets list
Example:
ConnectionStrings:DefaultConnection = Server=...
JwtSettings:Secret = MySecret...
ApiSettings:ApiKey = ABC123...
Be careful when using this command while screen-sharing or recording because it can display secret values.
12. Remove one secret
dotnet user-secrets remove "ApiSettings:ApiKey"
13. Remove all User Secrets
dotnet user-secrets clear
This removes the secrets associated with that project/UserSecretsId from the local secrets store.
14. Visual Studio Method
If you're using Visual Studio, you don't necessarily need to run the CLI commands manually.
Go to:
Solution Explorer
↓
Right-click Project
↓
Manage User Secrets
Visual Studio opens the corresponding secrets.json.
You can add:
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=PortfolioDb;..."
},
"JwtSettings": {
"Secret": "MyJwtSecret"
}
}
Then access them normally:
builder.Configuration.GetConnectionString("DefaultConnection");
and:
builder.Configuration["JwtSettings:Secret"];
15. appsettings.json vs User Secrets
| Feature | appsettings.json | User Secrets |
|---|---|---|
| Inside project | Yes | No |
| Usually source-controlled | Yes | No |
| Sensitive data | Avoid | Suitable for local development |
| Development use | Yes | Yes |
| Production secrets | No | No |
| Encrypted | No | No |
Access through IConfiguration |
Yes | Yes |
16. Development vs Production
A common architecture is:
ASP.NET Core
│
IConfiguration
│
┌────────────┴────────────┐
│ │
Development Production
│ │
User Secrets Azure Key Vault
│ │
Connection String Connection String
API Key API Key
JWT Secret JWT Secret
For example:
Local development
.NET User Secrets
Azure production
Azure Key Vault
+
Managed Identity
The application can continue using:
builder.Configuration["JwtSettings:Secret"];
The source of the configuration changes, while application code can remain largely the same.
17. Very Important: User Secrets are not encrypted
A common misunderstanding is:
"User Secrets securely encrypt my password."
No.
The local secrets.json is generally plain-text storage.
The main security benefit is:
Secret
↓
Stored outside project
↓
Not accidentally committed to Git
It primarily addresses source-control exposure, not every form of local-machine compromise.
18. What if the machine is corrupted?
As we discussed, User Secrets are local.
Developer Machine
↓
User Profile
↓
User Secrets
↓
secrets.json
If that local data is lost and isn't recoverable, the local User Secrets can be lost too.
Therefore:
User Secrets should not be treated as the master backup or production secret store.
19. Useful CLI Commands
| Requirement | Command |
|---|---|
| Initialize | dotnet user-secrets init |
| Set | dotnet user-secrets set "Key" "Value" |
| List | dotnet user-secrets list |
| Remove | dotnet user-secrets remove "Key" |
| Remove all | dotnet user-secrets clear |
Example:
dotnet user-secrets init
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=..."
dotnet user-secrets list
dotnet user-secrets remove "ConnectionStrings:DefaultConnection"
dotnet user-secrets clear
Key Points for Interview
- .NET User Secrets stores sensitive configuration for local development.
- Secrets are stored outside the project directory.
- Initialize using:
dotnet user-secrets init
- Store a secret using:
dotnet user-secrets set "Key" "Value"
- The project is associated with the secret store using:
<UserSecretsId>...</UserSecretsId>
- ASP.NET Core accesses User Secrets through the normal
IConfigurationsystem. - User Secrets can override values from
appsettings.jsonin the default development configuration. - Environment variables can override User Secrets in the standard configuration order.
- User Secrets are not encrypted.
- Don't use User Secrets as your production secret store.
- For production Azure applications, Azure Key Vault + Managed Identity is a common approach.
- The major benefit is keeping passwords, API keys, connection strings, etc. out of source control.