REST APIs are the backbone of modern applications, powering everything from mobile apps to enterprise integrations. But with this power comes responsibility; if APIs aren’t secure, they become an easy target for attackers.
In this article, we’ll walk through how to build secure REST APIs with ASP.NET Core , covering authentication, authorization, data protection, and real-world code samples .
Step 1: Start with HTTPS Everywhere
APIs must never be exposed over plain HTTP. Use HTTPS to encrypt communication.
In Program.cs :
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpsRedirection(); // Force HTTPS
app.MapControllers();
app.Run();
Step 2: Implement Authentication with JWT
Most secure APIs rely on JWT (JSON Web Tokens) for authentication.
Configure JWT in Program.cs :
builder.Services.AddAuthentication("Bearer")
.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"]))
};
});
Secure Controller with [Authorize] :
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
[HttpGet]
[Authorize]
public IActionResult GetOrders()
{
return Ok(new { Message = "Secure orders retrieved!" });
}
}
Step 3: Role-Based Authorization
Control who can access what using roles or policies.
[HttpPost]
[Authorize(Roles = "Admin")]
public IActionResult CreateOrder()
{
return Ok("Order created by Admin");
}
For more granular control, use policy-based authorization :
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("RequireManager", policy => policy.RequireRole("Manager"));
});
Step 4: Input Validation & Model Binding
Never trust user input—validate it.
public class OrderModel
{
[Required]
public string Product { get; set; }
[Range(1, 100)]
public int Quantity { get; set; }
}
[HttpPost]
public IActionResult PlaceOrder([FromBody] OrderModel model)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
return Ok("Order placed securely");
}
Step 5: Secure Cookies & Sessions (If Used)
If your API uses cookies (rare, but possible), enforce secure settings :
builder.Services.AddSession(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Strict;
});
Step 6: Protect Against CSRF
For APIs with JWT tokens : not required (tokens are sent in headers).
For MVC + API hybrid apps: use
@Html.AntiForgeryToken()and[ValidateAntiForgeryToken].
Step 7: Secure Data at Rest & In Transit
Use the Data Protection API to encrypt sensitive info.
Apply SQL parameterization to avoid injection.
var user = await _context.Users
.FirstOrDefaultAsync(u => u.Email == email);
Step 8: Enable Logging & Monitoring
Log authentication failures, suspicious requests, and unusual patterns.
Log.Logger = new LoggerConfiguration()
.WriteTo.File("logs/security.log")
.CreateLogger();
Integrate with Azure Monitor/Application Insights for better visibility.
Step 9: Throttle & Rate Limit
APIs without throttling are prone to DoS attacks. Use AspNetCoreRateLimit or built-in middleware.
builder.Services.AddRateLimiter(options =>
{
options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(
_ => RateLimitPartition.GetFixedWindowLimiter("global", _ =>
new FixedWindowRateLimiterOptions
{
PermitLimit = 100,
Window = TimeSpan.FromMinutes(1)
}));
});
Step 10: Keep Dependencies & Secrets Secure
Run
dotnet list package --vulnerableregularly.Store secrets in Azure Key Vault or User Secrets (never in
appsettings.json).
dotnet user-secrets set "Jwt:Key" "SuperSecretKey123!"
Secure API Checklist
Force HTTPS with redirection.
Use JWT for authentication.
Apply role/policy-based authorization.
Validate all input models.
Use parameterized queries (no raw SQL).
Encrypt sensitive data.
Enable logging & monitoring.
Apply rate limiting.
Store secrets securely.
Keep NuGet packages updated.
Conclusion
Building a REST API in ASP.NET Core is straightforward, but building a secure REST API requires discipline. By applying the techniques in this article—authentication, authorization, validation, encryption, logging, and monitoring you ensure your APIs are resilient against common attacks.
Security isn’t a one-time task. It’s a continuous process of auditing, patching, and improving. Start small, adopt these best practices, and make security part of your team’s development culture.

Join the conversation! Your thoughts help the community grow.