Programming

dotnet User Secrets vs appsettings.Development.json

Benefits of dotnet user secrets over a gitignored appsettings.Development.json: security, per-developer scope, tooling, env var comparison, and local secrets best practices.

1 answer 1 view

Is there any benefit to using .NET user secrets if I already add my development config file to .gitignore?

I keep appsettings.json with safe defaults and override it with appsettings.Development.json, which is gitignored. I understand user secrets are intended to prevent accidental commits and are only used for local development. Given this, why use user secrets instead of storing secrets in appsettings.Development.json?

Please explain:

  • What additional security or operational advantages do user secrets provide over a gitignored appsettings.Development.json?
  • Are there scenarios (team collaboration, backups, cross-machine development, tooling) where user secrets are safer or more convenient?
  • How do user secrets compare with environment variables or an external secrets manager for local development?
  • What are the recommended best practices for managing local development secrets in .NET?

Yes — there are real, practical benefits to using dotnet user secrets even when appsettings.Development.json is gitignored: user secrets store sensitive values outside the project tree, integrate with .NET configuration (and take precedence over JSON files), and reduce several leak and operational vectors that simple .gitignore doesn’t solve. They’re still a development convenience (the store is plaintext in your user profile), so pair them with environment variables or a proper secrets manager for CI/production.


Contents


Why use dotnet user secrets when appsettings.Development.json is gitignored?

Git‑ignoring appsettings.Development.json definitely prevents that file from being committed to your repository — and that’s a good start. But gitignore only stops one class of leakage: accidental check-ins into the VCS. There are other ways secrets leak or become operational pain points (backup folders, IDE sharing, packaging mistakes, unclear onboarding). User secrets put sensitive values in a per‑user, per‑project store outside the repository and outside the project folder, which reduces several of those risks while integrating directly with the .NET configuration system.

A key technical advantage is configuration precedence: the user secrets provider is registered after JSON configuration sources, so values stored with the secret manager override values in appsettings.json and appsettings.{Environment}.json without changing the checked-in files — see Microsoft’s configuration docs for details: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-10.0. That makes per-developer overrides simple and predictable.


Security and operational advantages of dotnet user secrets

What user secrets give you beyond “gitignored file”:

  • Physical separation from the repo and project folder. The secret JSON lives in your user profile (e.g., %APPDATA%\Microsoft\UserSecrets<id>\secrets.json on Windows or ~/.microsoft/usersecrets//secrets.json on macOS/Linux), not next to the code. That reduces accidental inclusion in project archives or ad-hoc file copies. Microsoft documents the use-case and location details here: https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-10.0.

  • Clear per-user scoping. Each developer has their own store keyed by the project’s UserSecretsId. You won’t overwrite someone else’s local values and you don’t have to create or manage separate files in the repo for each developer.

  • Integration with IConfiguration and predictable override behavior. Because the user-secrets provider is inserted after JSON files, you can keep safe defaults or placeholders in appsettings.json and let each developer override them via the secret store (no project file edits required). See Microsoft’s configuration precedence note: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-10.0.

  • Tooling and ergonomics. dotnet and IDEs (Visual Studio / Rider) support the Secret Manager and will update the project with a for you when you init, making setup straightforward. JetBrains and other blogs walk through the UX if you want a guided tour: https://blog.jetbrains.com/dotnet/2023/01/17/securing-sensitive-information-with-net-user-secrets/.

Important caveat — what user secrets do NOT give you:

  • They are not encrypted by default and are not a security boundary. The store is plaintext JSON tied to your user account. Treat them as a safer convenience than putting secrets in the repo, not as a replacement for a secrets manager.
  • They don’t help for CI/CD or production deployments. For those, use environment variables, vaults, or cloud secret services.

Scenarios where user secrets are safer or more convenient

Team collaboration

  • If everyone keeps appsettings.Development.json locally and gitignored, onboarding can be messy: new devs need a copy of the file or to remember keys and structure. With user secrets, you can check in an example or template file (no secret values) and have each developer run dotnet user-secrets set … or a bootstrap script to populate their local store. That avoids accidentally sharing real credentials while documenting what keys are required. Practical guides recommend keeping only placeholders in checked-in config and moving real values to user secrets: https://infinum.com/handbook/dotnet/best-practices/user-secrets.

Backups and cloud sync

  • A gitignored appsettings.Development.json still lives in the project folder and may be included in file-system backups or synced to Dropbox/OneDrive. User secrets are outside the workspace and reduce that risk (though note user profile folders can also be subject to backups — so don’t treat them as fully private).

Cross-machine development

  • User secrets are intentionally local. They don’t sync across your machines. That’s good for security but inconvenient if you regularly switch laptops. For multi-machine workflows you’ll need a secure way to migrate or re-create secrets (secure notes, a one-time transfer, or an internal vault). If you want secrets to travel with you securely, an external secrets manager or OS credential store is a better fit.

Tooling and scripts

  • CLI commands make scripting and automation easier: dotnet user-secrets init adds a to the project; dotnet user-secrets set and list let you bootstrap or inspect values programmatically. Example:
bash
dotnet user-secrets init
dotnet user-secrets set "ConnectionStrings:Default" "Server=.;Database=dev;User Id=sa;Password=..."
dotnet user-secrets list

That’s handy for local setup scripts and reproducible developer environments.

Debugging and local testing

  • Since the secrets are integrated into IConfiguration, you can test the exact same configuration path your app uses in production, but without storing real secrets in source. That reduces the mental gap between local and production configuration (while still forcing you to use a production-grade secret store later).

User secrets vs environment variables and external secrets managers

Short comparison and practical guidance:

  • dotnet user secrets

  • Pros: Easy to set up, per-user, integrates into IConfiguration, overrides appsettings.json, good for local dev and quick per-developer values.

  • Cons: Plaintext JSON in user profile, local-only (doesn’t sync), not suitable for CI/production.

  • Docs & guidance: https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-10.0

  • Environment variables

  • Pros: Standard for containers and CI; typically injected by the runtime/host, and they override JSON and user secrets. Good when you want to mimic production env.

  • Cons: Can leak into process lists, logs, or shell history if mishandled. Less discoverable than declared keys in appsettings.json.

  • Microsoft explicitly notes environment variables override previously specified configuration sources: https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-10.0

  • External secrets managers (Azure Key Vault, AWS Secrets Manager, HashiCorp Vault)

  • Pros: Centralized access control, auditing, rotation, secure storage and retrieval at runtime (the right choice for CI and production).

  • Cons: More setup and cost; you’ll need local strategies for development (see below).

  • For production and shared CI scenarios, these are the recommended approach — user secrets are explicitly for local development and not a production substitute.

Which to use when?

  • Local development: user secrets for developer‑specific values, environment variables when you want closer parity with production (or for containerized dev), or a local dev vault if your team runs one.
  • CI / production: environment variables or an external secrets manager — never user secrets.

Recommended best practices for managing local development secrets in .NET

A practical checklist you can adopt today:

  • Keep keys and safe defaults in appsettings.json (checked in). Don’t store real secrets there.
  • Add a template file to the repo, e.g. appsettings.Development.json.example, that shows the key structure but contains no secrets.
  • Use dotnet user secrets for per‑developer secrets:
  • Initialize: dotnet user-secrets init (adds to your project file)
  • Set a value: dotnet user-secrets set "MyApi:Key" "value"
  • Script setup: provide a secure bootstrap script (or document the dotnet user-secrets commands) for new devs.
  • Use environment variables to mirror production where appropriate (containers, Docker Compose), since env vars override user secrets and JSON files.
  • Centralize shared or production secrets in a real secret manager (Azure Key Vault, etc.) and grant devs scoped access if needed. Don’t copy production secrets into local user secrets.
  • Treat user secrets as a convenience, not a fortress. They reduce accidental commits and tidy per-developer values, but they’re plaintext — avoid storing high-value production credentials there.
  • Protect the development lifecycle: add secret-scanning to CI (or pre-commit hooks) so accidental secrets in any file are caught early.
  • Document the workflow in the repo README so new team members know how to initialize and populate their local secrets.
  • For cross-machine workflows, provide secure tooling (scripts that fetch secrets from a vault after authentication) instead of copying secrets files.

If you want a short how-to, sample workflow is:

  1. Check in appsettings.json with placeholders.
  2. Add appsettings.Development.json to .gitignore (or keep a .example file in VCS).
  3. Run dotnet user-secrets init and dotnet user-secrets set ... locally.
  4. Document commands in README and include a script for common keys.

For references and deeper reading see practical writeups and official guidance below.


Sources

  1. https://www.reddit.com/r/dotnet/comments/1498ubr/appsettingsjson_secrets_for_local_and_for/
  2. https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-10.0
  3. https://sam-lau.com/demystifying-net-application-development-configuration-user-secrets-vs-appsettings-development-json/
  4. https://stackoverflow.com/questions/56626305/why-should-i-use-user-secrets-only-in-the-development-environment
  5. https://mattjameschampion.com/2021/09/13/migrating-asp-net-core-development-secrets-out-of-appsettings-json/
  6. https://blog.jetbrains.com/dotnet/2023/01/17/securing-sensitive-information-with-net-user-secrets/
  7. https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-10.0
  8. https://stackoverflow.com/questions/66066865/net-5-secrets-json-appsettings-json-and-azure-application-settings
  9. https://infinum.com/handbook/dotnet/best-practices/user-secrets
  10. https://learn.microsoft.com/en-us/answers/questions/512933/does-my-user-secrets-store-have-incorrect-values

Conclusion

dotnet user secrets add value beyond a gitignored appsettings.Development.json by keeping sensitive values out of the project tree, giving per‑developer scope, and integrating with .NET configuration precedence so overrides are clean and predictable. They’re not an encryption or production solution — treat them as the right tool for local development convenience and combine them with environment variables or a central secrets manager for CI and production.

Authors
Verified by moderation
Moderation
dotnet User Secrets vs appsettings.Development.json