ASP.NET Core Security: 15 Best Practices for 2026
Security in ASP.NET Core has improved dramatically since the .NET Framework days, but the burden is still on the application developer to wire everything together correctly. Default-secure is a goal, not a guarantee.
This is the security checklist we apply to every production deployment on Adaptive's ASP.NET Core hosting, updated for .NET 10 LTS and the post-quantum cryptography wave hitting production in 2026.
15 | Non-Negotiable Practices
.NET 10 LTS | Updated For
PQ Crypto | Quantum-Safe Ready
OWASP | Core Ruleset WAF
!Security operations and monitoring
1. Enforce HTTPS Everywhere
Use UseHsts() and UseHttpsRedirection() in production:
if (!app.Environment.IsDevelopment())
{
app.UseHsts();
app.UseHttpsRedirection();
}
HSTS tells browsers to refuse HTTP for the configured duration (default 30 days; increase to a year for established sites). Combined with HSTS preloading, you eliminate downgrade attacks entirely.
Every Adaptive plan ships with FREE SSL on every site, so there's no excuse to leave HTTPS optional.
2. Adopt TLS 1.3 and Post-Quantum on .NET 10
.NET 10 LTS enables TLS 1.3 by default and introduces post-quantum cryptography support — ML-KEM (Key Encapsulation Mechanism) for key exchange, ML-DSA (Digital Signature Algorithm) for signatures. These are NIST-standardized algorithms designed to resist attacks from cryptographically relevant quantum computers.
> 🚀 Why this matters in 2026: "Harvest now, decrypt later" attacks make post-quantum crypto matter for any data with a 10+ year secrecy requirement. If you're hosting government, financial, or healthcare data, hybrid certificates start mattering this year. Our .NET 10 LTS hosting supports them out of the box.
3. Use ASP.NET Core Identity with Strong Password Hashing
ASP.NET Core Identity defaults to PBKDF2 with 100,000 iterations. Override to use higher iteration counts or Argon2id for new deployments:
services.Configure<PasswordHasherOptions>(o =>
{
o.IterationCount = 600_000;
});
Or replace IPasswordHasher with an Argon2id implementation (the Konscious.Security.Cryptography.Argon2 package is widely used).
4. Enable Anti-Forgery Tokens
Every form-based POST, PUT, PATCH, DELETE should use anti-forgery tokens:
builder.Services.AddAntiforgery(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
o.Cookie.HttpOnly = true;
});
On forms:
<form method="post" asp-controller="Account" asp-action="Login">
<input asp-for="Email" />
<input asp-for="Password" type="password" />
@Html.AntiForgeryToken()
</form>
[AutoValidateAntiforgeryToken] on the controller does the validation. For SPAs, send the token as a header on every state-changing request.
5. Set a Strict Content Security Policy
CSP is the single most effective mitigation for XSS — and it's badly underused. A starting policy:
app.Use(async (ctx, next) =>
{
ctx.Response.Headers["Content-Security-Policy"] =
"default-src 'self'; " +
"script-src 'self' 'nonce-" + nonce + "'; " +
"style-src 'self' 'unsafe-inline'; " +
"img-src 'self' data:; " +
"frame-ancestors 'none'; " +
"base-uri 'self'";
await next();
});
Use nonce- for inline scripts you control; phase out 'unsafe-inline' over time. Run securityheaders.com on your domain to validate.
6. Configure Rate Limiting Middleware
.NET 9+ ships native rate limiting:
builder.Services.AddRateLimiter(o =>
{
o.AddFixedWindowLimiter("login", opts =>
{
opts.PermitLimit = 5;
opts.Window = TimeSpan.FromMinutes(1);
opts.QueueLimit = 0;
});
});
app.UseRateLimiter();
app.MapPost("/login", LoginHandler).RequireRateLimiting("login");
> ⚠️ Critical endpoints to rate-limit: login, registration, password reset, OTP verification, and any expensive query endpoint that could be abused for amplification attacks.
7. Validate All Input — Yes, All of It
[ApiController] enables automatic model validation, but validation rules are only as good as your annotations. Use [Required], [StringLength], [Range], [RegularExpression], and FluentValidation for complex rules.
For SQL: never concatenate strings into queries. Use parameterized queries always, even when the input "can't" contain SQL. (Famous last words.)
8. Sanitize Output for the Right Context
HTML encoding ≠ JS encoding ≠ URL encoding. Razor encodes for HTML context by default; if you're rendering data into JavaScript, use System.Text.Json.JsonSerializer to escape correctly. For URLs, Uri.EscapeDataString.
@Html.Raw() is a code smell — every use should have a security review and a comment explaining why it's safe.
9. Store Secrets Outside Source Code
Never commit connection strings, API keys, or signing keys. The right tool for each environment:
| Environment | Recommended Secret Store |
|---|---|
| Development | User Secrets (dotnet user-secrets) |
| CI/CD | GitHub Secrets, Azure DevOps Library, AWS Parameter Store |
| Production | Azure Key Vault, AWS Secrets Manager, or appsettings.{env}.json outside web root with 400 permissions |
| Distributed teams | HashiCorp Vault with mTLS |
On Adaptive's hosting, appsettings.Production.json lives in your IIS application's config folder (not web root), and environment variables are configurable via Plesk.
10. Use Data Protection API Correctly
Cookies, anti-forgery tokens, and ASP.NET Core auth all depend on the Data Protection API. By default, keys are stored locally — if you're running multiple instances or recycling app pools, you'll see "Unprotect failed" errors.
For single-instance hosting (the default on our Developer plan), this is fine. For multi-instance, persist keys to a shared store:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"C:\inetpub\dpkeys"))
.ProtectKeysWithCertificate(cert);
11. Enable Secure Cookie Settings
builder.Services.ConfigureApplicationCookie(o =>
{
o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
o.Cookie.HttpOnly = true;
o.Cookie.SameSite = SameSiteMode.Strict;
o.SlidingExpiration = true;
o.ExpireTimeSpan = TimeSpan.FromHours(8);
});
| Setting | What It Defeats |
|---|---|
| SecurePolicy = Always | Transmission over plaintext HTTP |
| HttpOnly = true | JavaScript-based session theft |
| SameSite = Strict | Cross-site request forgery (CSRF) on GET requests |
| SlidingExpiration | Idle session abandonment without forcing re-login |
12. Disable Unused HTTP Methods
If you don't accept PUT or DELETE, don't let your application advertise them. IIS by default still responds to TRACE — disable it in your web.config:
<system.webServer>
<security>
<requestFiltering>
<verbs allowUnlisted="false">
<add verb="GET" allowed="true" />
<add verb="POST" allowed="true" />
</verbs>
</requestFiltering>
</security>
</system.webServer>
!Server logs and intrusion monitoring
13. Log Security Events Distinctly
Authentication failures, authorization denials, rate-limit hits, and CSP violations should log to a separate sink with longer retention. On Adaptive's plans, our log forwarding integrates with Datadog, Loki, and Sentry; security events can route to a dedicated index.
builder.Logging.AddFilter("Microsoft.AspNetCore.Authorization", LogLevel.Information);
builder.Logging.AddFilter("Microsoft.AspNetCore.Authentication", LogLevel.Information);
14. Patch Dependencies on a Schedule
Run dotnet list package --vulnerable weekly. Set up Dependabot or Renovate to file PRs automatically. .NET 10 LTS includes a built-in dotnet audit command that integrates with the NuGet vulnerability database.
> ✅ SLAs to commit to: 14-day patch SLA on Critical CVEs, 30 days on High. Faster if the vulnerability is exploitable in your specific attack surface.
15. Run a Security Header Audit Quarterly
Use Mozilla Observatory or securityheaders.com on every production hostname. Target an A+ rating:
Strict-Transport-SecuritywithincludeSubDomains; preloadContent-Security-Policywithout'unsafe-inline'(or with nonces)X-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originPermissions-Policylocking down unused browser APIs
Hosting-Layer Security Adaptive Provides
Even with perfect application code, your hosting layer has to cooperate. Every Adaptive plan includes:
| Layer | What's Included |
|---|---|
| Edge | DDoS protection, managed Web Application Firewall |
| Network | TLS termination, FREE SSL on every site |
| Host | Hardened Windows Server 2022 baseline, regular patching |
| IIS | Dedicated app pools (1–4 GB RAM by plan) — one breach doesn't pivot to others |
| Storage | High-performance SSD, automated backups |
| Database | SQL Server 2022 with Always Encrypted, ledger tables, Query Store |
| Infrastructure | AWS Virginia data center, 99.99% uptime SLA |
Frequently Asked Questions
Is ASP.NET Core Identity production-ready?
Yes — it's the same identity system used by Microsoft Learn, GitHub Education, and thousands of enterprise applications. Configure it correctly (Argon2id, sliding session, MFA), and it's as solid as anything in the market.
What's the right approach to MFA?
TOTP (Google Authenticator, Authy) for most apps. WebAuthn / passkeys for high-value accounts. Don't roll your own — use the .NET 10 LTS built-in IUserTwoFactorTokenProvider implementations.
How often should I rotate signing keys?
Data Protection keys rotate automatically every 90 days. JWT signing keys: every 12 months, or immediately on suspected compromise. Use kid (key ID) in JWT headers so you can rotate without invalidating in-flight tokens.
Does post-quantum crypto matter today?
For most apps, not yet — but "harvest now, decrypt later" attacks make it matter for any data with a 10+ year secrecy requirement. .NET 10 LTS supports it natively; enabling hybrid certs is a one-line change.
What about WAF false positives?
Tune iteratively: start with the standard rule set, monitor your false positive rate over the first week, then adjust signatures that conflict with your application's legitimate patterns (file uploads, rich-text editors, custom auth flows). Our support team can help interpret WAF logs for your specific application — just open a ticket from Plesk.
title: Host a Secure .NET Application on Hardened Infrastructure
description: Dedicated IIS app pools, WAF, DDoS protection, encrypted storage, post-quantum-ready TLS — all on a 99.99% uptime SLA. Plans from $9.49/mo.
cta-primary: ASP.NET Core Hosting | /asp-net-core-hosting
cta-secondary: .NET 10 LTS Hosting | /asp-net-core-10-hosting-plans
Want a second pair of eyes on your security configuration? Talk to our .NET team — we'll review your IIS config and Data Protection setup as part of any plan trial. Or see how customers handle real-world security workloads on our platform.