Securing Your API
Implement authentication for your ASP.NET Core API on Plesk Windows hosting.
Method 1: JWT Bearer Authentication
Best for: SPAs, mobile apps, microservices
// Install: dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
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"]!))
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
Generating JWT Tokens
[HttpPost("login")]
public IActionResult Login([FromBody] LoginDto login)
{
// Validate credentials
if (!ValidateUser(login.Username, login.Password))
return Unauthorized();
var claims = new[]
{
new Claim(ClaimTypes.Name, login.Username),
new Claim(ClaimTypes.Role, "User"),
new Claim("CustomClaim", "Value")
};
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]!));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _configuration["Jwt:Issuer"],
audience: _configuration["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddHours(1),
signingCredentials: creds);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token)
});
}
Method 2: API Key Authentication
Best for: Server-to-server, simple integrations
// Custom API Key handler
public class ApiKeyAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
private const string ApiKeyHeaderName = "X-Api-Key";
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.TryGetValue(ApiKeyHeaderName, out var apiKey))
return Task.FromResult(AuthenticateResult.Fail("API Key missing"));
var validApiKey = _configuration["ApiKey"];
if (apiKey != validApiKey)
return Task.FromResult(AuthenticateResult.Fail("Invalid API Key"));
var claims = new[] { new Claim(ClaimTypes.Name, "ApiClient") };
var identity = new ClaimsIdentity(claims, Scheme.Name);
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
}
// Register
builder.Services.AddAuthentication("ApiKey")
.AddScheme<AuthenticationSchemeOptions, ApiKeyAuthHandler>("ApiKey", null);
Method 3: OAuth 2.0 / OpenID Connect
Best for: Third-party integrations, enterprise SSO
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = "https://your-identity-provider.com";
options.ClientId = "your-client-id";
options.ClientSecret = "your-client-secret";
options.ResponseType = "code";
options.SaveTokens = true;
});
Protecting Endpoints
// Require authentication
[Authorize]
[HttpGet("protected")]
public IActionResult ProtectedEndpoint() => Ok("Authenticated!");
// Require specific role
[Authorize(Roles = "Admin")]
[HttpDelete("{id}")]
public IActionResult AdminOnly() => Ok("Admin access");
// Require policy
[Authorize(Policy = "RequireApiScope")]
public IActionResult PolicyProtected() => Ok();
Configuration (appsettings.json)
{
"Jwt": {
"Key": "YourSuperSecretKeyAtLeast32Characters!",
"Issuer": "https://yourdomain.com",
"Audience": "https://yourdomain.com"
},
"ApiKey": "your-api-key-here"
}
Security Best Practices
- Store secrets in environment variables, not appsettings
- Use HTTPS only
- Implement token refresh for JWTs
- Set appropriate token expiration
- Log authentication failures
- Implement rate limiting