APIs are the backbone of today’s digital ecosystem, powering mobile apps, SaaS platforms, IoT devices, and enterprise systems. But with their popularity comes a major challenge: security . According to OWASP, APIs are one of the top attack vectors for cybercriminals, often exploited through broken authentication, weak authorization, or data exposure.
In this article, we’ll take a practical, end-to-end journey through securing an ASP.NET Core Web API using JWT authentication and role-based authorization , with a real-world example: a Bookstore API .
Why API Security Matters
Imagine a bookstore API that exposes endpoints to manage books, authors, and sales. Without security:
Anyone could list books, update prices, or delete data.
Hackers could steal sensitive reports intended for admins only.
Attackers could flood the API with requests, causing downtime.
That’s why API security is non-negotiable.
Common API Security Threats
Before jumping into implementation, let’s recall the top threats (from OWASP API Top 10):
Broken Authentication: Weak login mechanisms or missing tokens.
Broken Authorization: Users accessing data or endpoints they shouldn’t.
Injection Attacks (SQL, NoSQL, Command): Malicious input executed by the system.
Sensitive Data Exposure: Sending unencrypted or excessive data.
Rate Limiting & DoS Attacks – Flooding APIs with requests.
Improper Logging & Monitoring – No visibility into attacks.
Best Practices for API Security
To mitigate these threats, adopt a defense-in-depth approach:
Use HTTPS everywhere—no plain HTTP.
Authentication & Authorization —JWT or OAuth 2.0 with RBAC/Policies.
Validate Inputs —prevent SQL injection and NoSQL injection.
Rate Limiting & Throttling —prevent abuse and DoS attacks.
Centralized Secret Management —Azure Key Vault or AWS Secrets Manager.
Error Handling —don’t leak stack traces.
Monitoring & Logging —track security events with Serilog or App Insights.
Implementation: Securing a Bookstore API with JWT
We’ll now build a secure Bookstore API in ASP.NET Core Web API with:
Step 1. Create Project
dotnet new webapi -n BookstoreApi
cd BookstoreApi
Step 2. Add NuGet Package
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Step 3. Configure Authentication & Authorization ( Program.cs
)
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Add Authentication with JWT
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "https://api.bookstore.com",
ValidAudience = "https://api.bookstore.com"
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("SuperSecretKey12345")) // use Key Vault in production
};
});
// Authorization Policies
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Step 4. Create Auth Controller ( Controllers/AuthController.cs
)
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace BookstoreApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
[HttpPost("login")]
public IActionResult Login(string username, string password)
{
// Demo validation (replace with ASP.NET Identity or DB check in production)
if (username == "admin" && password == "password")
{
var claims = new[]
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.Role, "Admin")
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SuperSecretKey12345"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "https://api.bookstore.com",
audience: "https://api.bookstore.com",
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
}
return Unauthorized();
}
}
}
Step 5. Create Secure Data Controller ( Controllers/SecureDataController.cs
)
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace BookstoreApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class SecureDataController : ControllerBase
{
// Accessible by any authenticated user
[HttpGet("books")]
[Authorize]
public IActionResult GetBooks() =>
Ok("List of available books. (Authenticated users only)");
// Accessible only by Admin role
[HttpGet("admin/reports")]
[Authorize(Policy = "AdminOnly")]
public IActionResult GetAdminReports() =>
Ok("Sensitive sales reports. (Admins only)");
}
}
Testing the API
Log in to get a JWT token
POST https://api.bookstore.com/api/auth/login
Body: { "username": "admin", "password": "password" }
Response
{ "token": "eyJhbGciOiJIUzI1NiIsIn..." }
Access books endpoint. (user-protected)
GET https://api.bookstore.com/api/securedata/books
Authorization: Bearer <token>
Access admin reports endpoint (admin-only)
GET https://api.bookstore.com/api/securedata/admin/reports
Authorization: Bearer <token>
Enhancing Security Further
Store SuperSecretKey12345
in Azure Key Vault or AWS Secrets Manager.
Use the AspNetCoreRateLimit NuGet package to apply rate limiting.
Enforce HTTPS redirection
app.UseHttpsRedirection();
Monitor API usage with Serilog and Application Insights.
Regularly patch dependencies and update the .NET runtime.
Conclusion
API security is not just about authentication; it’s a multi-layered defense strategy. In this article, we:
Reviewed the OWASP API Top 10 threats.
Implemented JWT authentication in ASP.NET Core.
Applied role-based authorization for sensitive endpoints.
Discussed enterprise-grade enhancements like rate limiting and secret management.
With these practices, your ASP.NET Core Web APIs will be secure, reliable, and production-ready.