ASP.NET Core Application Security Essentials Print

  • 0

ASP.NET Core Application Security

Essential security practices for ASP.NET Core 8/9/10 applications.

1. Authentication Configuration

Cookie Authentication Security

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.Cookie.HttpOnly = true;        // Prevent JS access
        options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // HTTPS only
        options.Cookie.SameSite = SameSiteMode.Strict; // Prevent CSRF
        options.ExpireTimeSpan = TimeSpan.FromHours(8);
        options.SlidingExpiration = true;
    });

JWT Token Security

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
        };
    });

2. CSRF Protection

Enable Anti-Forgery Tokens

// In Program.cs
builder.Services.AddAntiforgery(options =>
{
    options.HeaderName = "X-CSRF-TOKEN";
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});

// In controllers
[ValidateAntiForgeryToken]
public IActionResult UpdateProfile(ProfileModel model) { ... }

In Razor Views

<form method="post">
    @Html.AntiForgeryToken()
    <!-- form fields -->
</form>

3. Input Validation

Model Validation Attributes

public class UserRegistration
{
    [Required]
    [StringLength(100, MinimumLength = 2)]
    public string Name { get; set; }

    [Required]
    [EmailAddress]
    public string Email { get; set; }

    [Required]
    [StringLength(100, MinimumLength = 8)]
    [RegularExpression(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$",
        ErrorMessage = "Password must contain upper, lower, and number")]
    public string Password { get; set; }
}

Controller Validation

[HttpPost]
public IActionResult Register(UserRegistration model)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    // Process valid input
}

4. XSS Prevention

Output Encoding (Automatic in Razor)

<!-- Safe - automatically encoded -->
<p>@Model.UserInput</p>

<!-- Dangerous - only use for trusted HTML -->
@Html.Raw(Model.TrustedHtml)

Manual Encoding

using System.Text.Encodings.Web;

var encoder = HtmlEncoder.Default;
var safeOutput = encoder.Encode(userInput);

5. Rate Limiting (ASP.NET Core 7+)

// In Program.cs
builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter("Api", opt =>
    {
        opt.PermitLimit = 100;
        opt.Window = TimeSpan.FromMinutes(1);
        opt.QueueLimit = 0;
    });
});

app.UseRateLimiter();

// On endpoints
[EnableRateLimiting("Api")]
public class ApiController : ControllerBase { }

6. Secrets Management

User Secrets (Development)

# Initialize
dotnet user-secrets init

# Set secret
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=..."

Environment Variables (Production)

// Access in code
var connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION");

// Or via configuration
var connectionString = builder.Configuration["ConnectionStrings:DefaultConnection"];

7. Secure File Uploads

[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
    // Validate file type
    var allowedExtensions = new[] { ".jpg", ".png", ".pdf" };
    var extension = Path.GetExtension(file.FileName).ToLowerInvariant();

    if (!allowedExtensions.Contains(extension))
        return BadRequest("Invalid file type");

    // Validate file size (5MB max)
    if (file.Length > 5 * 1024 * 1024)
        return BadRequest("File too large");

    // Generate safe filename
    var safeFileName = $"{Guid.NewGuid()}{extension}";

    // Save outside web root
    var path = Path.Combine(_uploadsPath, safeFileName);
    using var stream = new FileStream(path, FileMode.Create);
    await file.CopyToAsync(stream);

    return Ok();
}

Security Configuration Checklist

Item Status
HTTPS enforced
Security headers configured
CSRF protection enabled
Input validation on all forms
Authentication properly configured
Secrets not in source code
File uploads validated
Rate limiting enabled
Error pages hide sensitive info

Was this answer helpful?

« Back