Securing Web APIs is a critical aspect of building modern, scalable, and trustworthy applications. In ASP.NET Core, Microsoft provides a wide range of built-in features to help developers protect their APIs from unauthorized access, data leakage, and misuse. This tutorial provides a comprehensive guide on how to secure your Web API in .NET using Authentication, Authorization, HTTPS, CORS, API Keys, and JWT (JSON Web Tokens).
Web APIs are often the backbone of modern applications, exposing business logic and data to external clients. Failing to secure APIs can result in:
Authentication is the process of verifying the identity of a user or service. ASP.NET Core supports various authentication mechanisms such as JWT, Cookie, OAuth2, and third-party providers like Google and Microsoft.
Authorization determines whether an authenticated user has permission to access a specific resource. ASP.NET Core uses role-based and policy-based authorization.
Always use HTTPS to encrypt the data in transit. ASP.NET Core apps are configured to use HTTPS by default in production.
CORS controls which external domains are allowed to access your Web API. Misconfigured CORS can lead to security vulnerabilities.
API keys are simple tokens used to authenticate requests. While not ideal for highly secure APIs, they are suitable for basic security in public APIs.
JWT is a stateless authentication method where the token carries information and is signed by the server. It is widely used for SPAs and mobile apps.
To enforce HTTPS in ASP.NET Core, use middleware in the Startup.cs class:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
CORS allows your API to be called from approved client domains. In Startup.cs, register and use CORS:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
builder => builder.WithOrigins("https://trustedclient.com")
.AllowAnyMethod()
.AllowAnyHeader());
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app)
{
app.UseCors("AllowSpecificOrigin");
}
Use the [Authorize] attribute to restrict access to authenticated users only.
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
[Authorize]
[HttpGet]
public IActionResult GetOrders()
{
return Ok(new[] { "Order1", "Order2" });
}
}
Install the JWT package:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Configure JWT Authentication in Program.cs or Startup.cs:
var key = Encoding.ASCII.GetBytes("YourSecureKeyHere");
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
[HttpPost("login")]
public IActionResult Login(UserLogin login)
{
if (login.Username == "admin" && login.Password == "password")
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("YourSecureKeyHere");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, login.Username)
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
return Ok(new { Token = tokenString });
}
return Unauthorized();
}
Configure roles in the token and decorate the method:
[Authorize(Roles = "Admin")]
[HttpGet("admin")]
public IActionResult GetAdminData()
{
return Ok("This is for admins only");
}
ASP.NET Core Identity is a full-fledged membership system. To use Identity:
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
In Program.cs:
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer("YourConnectionString"));
builder.Services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
builder.Services.AddAuthentication(...);
Use middleware to validate API keys:
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private const string API_KEY_HEADER = "X-API-KEY";
private const string VALID_API_KEY = "123456";
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (!context.Request.Headers.TryGetValue(API_KEY_HEADER, out var extractedApiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("API Key is missing");
return;
}
if (!VALID_API_KEY.Equals(extractedApiKey))
{
context.Response.StatusCode = 403;
await context.Response.WriteAsync("Invalid API Key");
return;
}
await _next(context);
}
}
Configure production environments to enforce HTTPS and optionally use mutual TLS with certificates.
app.UseHttpsRedirection();
Use built-in logging and monitoring to detect suspicious activity:
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
Securing your ASP.NET Core Web API is essential to building robust, scalable, and secure web applications. Whether you're using JWT, Identity, or API keys, the principles of HTTPS, authentication, and authorization form the foundation of a secure API. Follow the practices outlined in this tutorial to prevent unauthorized access and protect your application data effectively.
By implementing a multi-layered security approachβvalidating input, enforcing HTTPS, leveraging token-based authentication, and applying strict CORS policiesβyou'll be prepared to secure your .NET APIs in any production environment.
Copyrights © 2024 letsupdateskills All rights reserved