Chd.Library.Security
8.6.0
dotnet add package Chd.Library.Security --version 8.6.0
NuGet\Install-Package Chd.Library.Security -Version 8.6.0
<PackageReference Include="Chd.Library.Security" Version="8.6.0" />
<PackageVersion Include="Chd.Library.Security" Version="8.6.0" />
<PackageReference Include="Chd.Library.Security" />
paket add Chd.Library.Security --version 8.6.0
#r "nuget: Chd.Library.Security, 8.6.0"
#:package Chd.Library.Security@8.6.0
#addin nuget:?package=Chd.Library.Security&version=8.6.0
#tool nuget:?package=Chd.Library.Security&version=8.6.0
Library.Security π
Library.Security is a production-ready authentication and authorization library for .NET 8 applications. It provides JWT token management, cookie-based authentication, IP filtering middleware, and secure user login workflowsβall with minimal configuration. Part of the CHD (Cleverly Handle Difficulty) ecosystem.
What Does It Do?
Library.Security provides enterprise-grade security features:
- JWT Authentication: Symmetric & asymmetric token validation with configurable expiration
- Cookie Authentication: Session-based auth for Razor Pages and MVC apps
- IP Whitelisting: Middleware to restrict access by IP address
- Secure Login: Built-in
SecurityContextfor user authentication workflows - Token Services: Generate, validate, and refresh JWT tokens
- Integration Ready: Works seamlessly with ASP.NET Core authentication pipeline
Who Is It For?
- ASP.NET Core Developers building secure Web APIs, Razor Pages, or MVC apps
- Teams needing quick JWT/Cookie auth setup without boilerplate
- Microservices requiring centralized token validation
- Projects with IP filtering requirements (VPN, internal tools, admin panels)
π Table of Contents
- Why Library.Security?
- Installation
- Quick Start Guide
- Configuration Reference
- Real-World Examples
- API Reference
- Security Best Practices
- Troubleshooting
- FAQ
- Related CHD Packages
Stop Writing Auth Boilerplate! β°
Every project needs authentication. Stop copy-pasting JWT configuration code. Library.Security provides production-ready auth in 3 lines.
The Problem π«
// β Every project repeats this 100+ line JWT setup:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)),
ValidateIssuer = true,
ValidIssuer = issuer,
ValidateAudience = true,
ValidAudience = audience,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
// ... plus session config, token service, cookie setup, IP filtering...
The Solution β
// β
One line for JWT auth
builder.Services.UseJwtTokenAuthorization(builder.Configuration);
// β
Or one line for Cookie auth
var app = builder.UseCookieAuthorization();
// β
Login in 2 lines
var token = await SecurityContext.Login(this, userModel);
if (!string.IsNullOrEmpty(token)) return RedirectToAction("Dashboard");
Why Library.Security?
| Problem | Without Library.Security | With Library.Security |
|---|---|---|
| JWT Setup | 100+ lines of boilerplate per project | 1 line: .UseJwtTokenAuthorization() |
| Cookie Auth | Manual claims, session config, lifetime | 1 line: .UseCookieAuthorization() |
| IP Whitelisting | Custom middleware, header parsing | Built-in middleware + config |
| Token Generation | Manual JWT creation, signing, validation | ITokenService with symmetric/asymmetric support |
| Secure Login | Custom authentication logic | SecurityContext.Login() |
| Token Refresh | Complex expiration handling | Auto-refresh support |
Key Benefits:
- β‘ 90% less code - No auth boilerplate
- π Production-tested - Used in CHD ecosystem
- π¨ Clean APIs - Integrates seamlessly with ASP.NET Core
- π‘οΈ Secure by default - Industry-standard JWT practices
- π§ Flexible - Supports symmetric, asymmetric, and cookie auth
- π Well-documented - Real examples for every scenario
Installation
dotnet add package Library.Security
NuGet Package Manager:
Install-Package Library.Security
Package Reference (.csproj):
<PackageReference Include="Library.Security" Version="8.5.7" />
Quick Start Guide
1οΈβ£ JWT Authentication (Symmetric)
Step 1: Add Configuration
// appsettings.json
{
"Jwt": {
"Key": "YOUR_256_BIT_SECRET_KEY_MINIMUM_32_CHARACTERS_LONG!!",
"Issuer": "https://your-auth-server.com",
"Audience": "your-api-audience",
"Mode": "Symmetric"
}
}
Step 2: Configure Services
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// β
One line JWT setup
builder.Services.UseJwtTokenAuthorization(builder.Configuration);
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Step 3: Protect Your Endpoints
[ApiController]
[Route("api/[controller]")]
[Authorize] // β
Requires valid JWT token
public class ProductsController : ControllerBase
{
[HttpGet]
public IActionResult GetProducts()
{
return Ok(new { Message = "Secure data!" });
}
[HttpGet("public")]
[AllowAnonymous] // Public endpoint
public IActionResult GetPublicData()
{
return Ok(new { Message = "No auth needed" });
}
}
2οΈβ£ JWT Authentication (Asymmetric - RSA)
When Your Architecture Needs Maximum Security (Microservices, Distributed Systems)
π Why Asymmetric JWT?
| Problem with Symmetric | Asymmetric Solution |
|---|---|
| Same key signs & validates | Private key signs, public key validates |
| Key must be shared with all services | Only auth server has private key |
| One compromised service = system-wide breach | Compromised API can't forge tokens |
| Single point of failure | Distributed validation, centralized generation |
| Not suitable for public APIs | Public key can be shared safely |
π When to Use Asymmetric JWT (RSA)?
| Scenario | Recommendation | Reason |
|---|---|---|
| Single monolithic app | β Symmetric | Simpler, faster |
| Microservices (3+ APIs) | β Asymmetric | Security isolation |
| Auth server + multiple services | β Asymmetric | Private key stays on auth server |
| Third-party API integration | β Asymmetric | Can share public key safely |
| High-security requirements | β Asymmetric | No shared secrets |
| Public-facing APIs | β Asymmetric | Industry standard |
π Quick Setup (Asymmetric)
Step 1: Generate RSA Key Pair
// Run once to generate keys
using Library.Security.Services;
TokenServicev2.GenerateRsaKeys(
privateKeyPath: "Keys/private_key.xml",
publicKeyPath: "Keys/public_key.xml"
);
// β οΈ Store private key securely (Azure Key Vault, AWS Secrets Manager)
// β
Public key can be shared with all services
Step 2: Configuration (Auth Server - Private Key)
// appsettings.json (Auth Server only)
{
"Jwt": {
"Mode": "Asymmetric",
"PrivateKeyPath": "Keys/private_key.xml",
"PublicKeyPath": "Keys/public_key.xml",
"Issuer": "https://auth-server.com",
"Audience": "all-services"
}
}
Step 3: Configuration (API Services - Public Key Only)
// appsettings.json (Catalog API, Orders API, Inventory API)
{
"Jwt": {
"Mode": "Asymmetric",
"PublicKeyPath": "Keys/public_key.xml",
"Issuer": "https://auth-server.com",
"Audience": "all-services"
}
}
Step 4: Enable Asymmetric JWT
// Program.cs (both Auth Server and API Services)
var builder = WebApplication.CreateBuilder(args);
// β
Asymmetric JWT authentication
builder.Services.UseJwtTokenAuthorizationv2(builder.Configuration);
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
ποΈ Real-World Architecture Example
Scenario: E-Commerce Platform with Microservices
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CLIENT (Mobile/Web) β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β
β 1. Login (username/password)
βΌ
ββββββββββββββββββββββββββββββ
β AUTH SERVER β
β (Private Key π) β
β - Validates credentials β
β - Signs JWT with RSA β
β - Returns token β
ββββββββββββββ¬ββββββββββββββββ
β
β 2. JWT Token
βΌ
ββββββββββββββββββββββββββββββ
β CLIENT β
β Stores token β
ββββββββββββββ¬ββββββββββββββββ
β
β 3. API Requests with JWT
βββββββββββββββββββΌββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β CATALOG API β β ORDERS API β β PAYMENT API β
β (Public Key)β β (Public Key)β β (Public Key)β
β β
Validatesβ β β
Validatesβ β β
Validatesβ
β β Can't β β β Can't β β β Can't β
β forge β β forge β β forge β
βββββββββββββββ βββββββββββββββ βββββββββββββββ
π» Complete Code Example
Auth Server (Token Generation with Private Key):
// Controllers/AuthController.cs (Auth Server)
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly ITokenService _tokenService; // TokenServicev2 for asymmetric
private readonly UserService _userService;
public AuthController(ITokenService tokenService, UserService userService)
{
_tokenService = tokenService;
_userService = userService;
}
[HttpPost("login")]
[AllowAnonymous]
public IActionResult Login([FromBody] UserModel model)
{
// Validate credentials
var user = _userService.ValidateUser(model.UserName, model.Password);
if (user == null)
return Unauthorized(new { Message = "Invalid credentials" });
// β
Generate JWT using RSA private key
var token = _tokenService.BuildToken(new UserDTO
{
UserId = user.Id,
UserName = user.Username,
Role = user.Role
});
return Ok(new
{
Token = token,
ExpiresIn = 3600, // 1 hour
TokenType = "Bearer"
});
}
}
Catalog API (Token Validation with Public Key):
// Controllers/ProductsController.cs (Catalog API)
[ApiController]
[Route("api/[controller]")]
[Authorize] // β
Validates token with public key (can't forge tokens)
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
[HttpGet("{id}")]
public IActionResult GetProduct(int id)
{
// Token validated by middleware using public key
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var role = User.FindFirst(ClaimTypes.Role)?.Value;
var product = _productService.GetProduct(id);
return Ok(product);
}
}
Orders API (Also Validates with Public Key):
// Controllers/OrdersController.cs (Orders API)
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class OrdersController : ControllerBase
{
[HttpPost]
public IActionResult CreateOrder([FromBody] OrderRequest request)
{
// β
Same token works across all services
// β
Each service validates independently with public key
// β Compromised service can't create fake tokens
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
// Create order logic...
return Ok(new { OrderId = 12345 });
}
}
π Security Benefits
| Aspect | Symmetric (Shared Secret) | Asymmetric (RSA) |
|---|---|---|
| Key Distribution | All services need secret key | Only public key distributed |
| Breach Impact | One compromised service = all tokens can be forged | Compromised service can't forge tokens |
| Key Rotation | Update all services simultaneously | Update only auth server, APIs auto-refresh |
| Third-Party Access | Can't share key safely | Can share public key with partners |
| Compliance | Basic security | Meets PCI-DSS, HIPAA, SOC2 |
π― Best Practices for Asymmetric JWT
β Store Private Key Securely
// β NEVER commit private key to source control // β Use Azure Key Vault var keyVaultUrl = "https://your-vault.vault.azure.net/"; var privateKey = await keyVaultClient.GetSecretAsync(keyVaultUrl, "jwt-private-key"); // β Or environment variable var privateKey = Environment.GetEnvironmentVariable("JWT_PRIVATE_KEY");β Rotate Keys Regularly
// Generate new key pair every 90 days TokenServicev2.GenerateRsaKeys( "Keys/private_key_v2.xml", "Keys/public_key_v2.xml" ); // Support both old and new keys during transitionβ Use Strong Key Size
// Minimum 2048-bit RSA keys (default in TokenServicev2) // For high security: 4096-bitβ Implement Key Versioning
{ "Jwt": { "Keys": [ { "Version": "v2", "PublicKeyPath": "Keys/public_key_v2.xml" }, { "Version": "v1", "PublicKeyPath": "Keys/public_key_v1.xml" } ] } }
β‘ Performance Consideration
| Operation | Symmetric (HS256) | Asymmetric (RS256) |
|---|---|---|
| Token Generation | ~0.1 ms | ~2 ms |
| Token Validation | ~0.1 ms | ~0.5 ms |
| Verdict | Faster | Slightly slower, but negligible in most apps |
π‘ Recommendation: Use asymmetric JWT for microservices despite 20x slower generationβsecurity benefits outweigh 2ms overhead.
3οΈβ£ Cookie Authentication (Razor Pages)
Perfect for Razor Pages apps with server-side rendering:
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
// β
Cookie authentication with one line
var app = builder.UseCookieAuthorization();
app.MapRazorPages();
app.Run();
appsettings.json:
{
"SecurityConfig": {
"Issuer": "https://your-app.com",
"Audience": "your-app-users",
"Key": "YOUR_SECRET_KEY"
}
}
Login Page Example:
// Pages/Login.cshtml.cs
public class LoginModel : PageModel
{
[BindProperty]
public string Username { get; set; }
[BindProperty]
public string Password { get; set; }
public async Task<IActionResult> OnPostAsync()
{
var userModel = new UserModel
{
UserName = Username,
Password = Password.ToMd5() // Hash password
};
// β
Built-in secure login
bool success = await SecurityContext.LoginCookieAuthentitation(
this,
userModel,
ValidateUser // Your validation function
);
if (success)
return RedirectToPage("/Dashboard");
else
return Page(); // Show error
}
private UserDTO ValidateUser(UserModel model)
{
// Your database validation logic
var user = _db.Users.FirstOrDefault(u =>
u.Username == model.UserName &&
u.PasswordHash == model.Password);
if (user == null) return null;
return new UserDTO
{
UserId = user.Id,
UserName = user.Username,
Role = user.Role
};
}
}
4οΈβ£ IP Whitelisting Middleware
Restrict access to specific IP addresses (VPN, internal tools, admin panels):
Step 1: Configuration
// appsettings.json
{
"AllowedIPs": [
"192.168.1.100",
"10.0.0.50",
"203.0.113.42"
]
}
Step 2: Enable Middleware
// Program.cs
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// β
IP filtering middleware
app.UseIpFilterMiddleware();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Features:
- β
Handles
X-Forwarded-Forheader (proxies, load balancers) - β 20-second cache for performance
- β
Returns
403 Forbiddenfor blocked IPs - β Whitelist reloads automatically
5οΈβ£ Secure Login with SecurityContext
For Web APIs with external token generation service:
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
[HttpPost("login")]
[AllowAnonymous]
public async Task<IActionResult> Login([FromBody] UserModel userModel)
{
// Hash password before validation
userModel.Password = userModel.Password?.ToMd5();
// β
SecurityContext handles token generation via external service
var token = await SecurityContext.Login(this, userModel);
if (string.IsNullOrEmpty(token))
{
return Unauthorized(new { Message = "Invalid credentials" });
}
// Token stored in session automatically
return Ok(new
{
Token = token,
ExpiresIn = 3600 // 1 hour
});
}
}
How It Works:
SecurityContext.Login()posts credentials toJwt:IssuerURL (your token service)- Token service validates user and generates JWT
- Token stored in
HttpContext.Session["Token"] - Returns token for client storage (localStorage, cookie, etc.)
Configuration Reference
JWT Configuration (Symmetric)
{
"Jwt": {
"Key": "YOUR_MINIMUM_32_CHARACTER_SECRET_KEY",
"Issuer": "https://your-auth-server.com",
"Audience": "your-api-name",
"Mode": "Symmetric"
}
}
| Property | Required | Description |
|---|---|---|
Key |
β Yes | Secret key for signing tokens (min 32 chars for HS256) |
Issuer |
β Yes | Token issuer URL (your auth server) |
Audience |
β Yes | Token audience (your API name) |
Mode |
β No | "Symmetric" (default) or "Asymmetric" |
JWT Configuration (Asymmetric - RSA)
{
"Jwt": {
"Mode": "Asymmetric",
"PublicKeyPath": "Keys/public_key.xml",
"PrivateKeyPath": "Keys/private_key.xml",
"Issuer": "https://your-auth-server.com",
"Audience": "your-api-name"
}
}
Generate RSA Keys:
TokenServicev2.GenerateRsaKeys("Keys/private_key.xml", "Keys/public_key.xml");
Cookie Authentication Configuration
{
"SecurityConfig": {
"Issuer": "https://your-app.com",
"Audience": "your-app-users",
"Key": "YOUR_SECRET_KEY"
}
}
Cookie Options (automatic):
- Expiration: 20 minutes (sliding)
- SameSite: Strict
- HttpOnly: true
- AccessDeniedPath:
/Forbidden/
IP Whitelist Configuration
{
"AllowedIPs": [
"192.168.1.0/24",
"10.0.0.50",
"203.0.113.42"
]
}
Cache: 20 seconds (auto-reload)
Real-World Examples
Example 1: Razor Pages E-Commerce with Cookie Auth
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.UseCookieAuthorization(); // β
Cookie auth
app.MapRazorPages();
app.Run();
// Pages/Account/Login.cshtml.cs
public class LoginModel : PageModel
{
private readonly ShopDbContext _db;
public LoginModel(ShopDbContext db) => _db = db;
[BindProperty]
public string Email { get; set; }
[BindProperty]
public string Password { get; set; }
public async Task<IActionResult> OnPostAsync()
{
var userModel = new UserModel
{
UserName = Email,
Password = Password.ToMd5()
};
// β
Secure login with cookie
bool success = await SecurityContext.LoginCookieAuthentitation(
this,
userModel,
user =>
{
var dbUser = _db.Users.FirstOrDefault(u =>
u.Email == user.UserName &&
u.PasswordHash == user.Password);
if (dbUser == null) return null;
return new UserDTO
{
UserId = dbUser.Id,
UserName = dbUser.Email,
Role = dbUser.Role
};
}
);
if (success)
return RedirectToPage("/Dashboard");
ModelState.AddModelError("", "Invalid email or password");
return Page();
}
}
// Pages/Dashboard.cshtml.cs
[Authorize] // β
Requires authentication
public class DashboardModel : PageModel
{
public string Username => User.Identity?.Name ?? "Guest";
public void OnGet()
{
// User is authenticated
}
}
Example 2: Web API with JWT + IP Filtering
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// β
JWT authentication
builder.Services.UseJwtTokenAuthorization(builder.Configuration);
builder.Services.AddControllers();
var app = builder.Build();
// β
IP filtering for admin routes
app.UseWhen(
context => context.Request.Path.StartsWithSegments("/api/admin"),
appBuilder => appBuilder.UseIpFilterMiddleware()
);
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
// Controllers/AdminController.cs
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class AdminController : ControllerBase
{
// β
Only accessible from whitelisted IPs
[HttpGet("users")]
public IActionResult GetUsers()
{
return Ok(new { Message = "Admin data" });
}
}
Example 3: Microservices with Centralized Auth
// Auth Service (Token Generation)
[HttpPost("token")]
public IActionResult GenerateToken([FromBody] UserModel model)
{
var user = ValidateUser(model);
if (user == null) return Unauthorized();
var token = _tokenService.BuildToken(user);
return Ok(new { Token = token });
}
// Product Service (Token Validation)
var builder = WebApplication.CreateBuilder(args);
// β
Validate tokens from Auth Service
builder.Services.UseJwtTokenAuthorization(builder.Configuration);
// appsettings.json in Product Service
{
"Jwt": {
"Issuer": "https://auth-service.com", // β
Same issuer
"Audience": "product-service",
"Key": "SHARED_SECRET_KEY" // β
Same key
}
}
API Reference
Extension Methods
IServiceCollection Extensions
// JWT authentication (symmetric)
services.UseJwtTokenAuthorization(configuration);
// JWT authentication (asymmetric RSA)
services.UseJwtTokenAuthorizationv2(configuration);
// Cookie authentication
var app = builder.UseCookieAuthorization();
SecurityContext Class
// JWT login (calls external token service)
Task<string> SecurityContext.Login(
ControllerBase controller,
UserModel userModel
)
// Cookie login (local validation)
Task<bool> SecurityContext.LoginCookieAuthentitation(
Controller controller,
UserModel userModel,
Func<UserModel, UserDTO> validationFunc
)
ITokenService Interface
public interface ITokenService
{
string BuildToken(UserDTO user);
bool ValidateToken(string token);
ClaimsPrincipal GetPrincipalFromToken(string token);
}
Models
public class UserModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
public class UserDTO
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Role { get; set; }
}
public class SecurityConfig
{
public string Issuer { get; set; }
public string Audience { get; set; }
public string Key { get; set; }
}
Security Best Practices
- β Use HTTPS only - JWT tokens are vulnerable to interception
- β Store keys in environment variables - Never commit secrets to source control
- β
Rotate keys regularly - Update
Jwt:Keyevery 90 days - β Use asymmetric keys for microservices - Private key only on auth service
- β
Hash passwords - Use
.ToMd5()or better:BCrypt,PBKDF2 - β Set short token lifetimes - 15-60 minutes for sensitive APIs
- β Implement refresh tokens - For long-lived sessions
- β οΈ Don't use MD5 for production passwords - Use ASP.NET Core Identity or BCrypt
Troubleshooting
Issue: 401 Unauthorized even with valid token
Cause: Issuer/Audience mismatch or expired token
Fix:
// Check token validation parameters
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "YOUR_ISSUER", // β
Must match token's "iss" claim
ValidateAudience = true,
ValidAudience = "YOUR_AUDIENCE", // β
Must match token's "aud" claim
ValidateLifetime = true // β
Checks "exp" claim
};
Issue: IP filtering blocks legitimate users
Cause: Proxy/load balancer not forwarding real client IP
Fix:
// Enable X-Forwarded-For header forwarding
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
// BEFORE IP filter middleware
app.UseIpFilterMiddleware();
Issue: "Key length is too short" error
Cause: JWT key must be at least 256 bits (32 characters) for HS256
Fix:
{
"Jwt": {
"Key": "THIS_IS_A_VERY_LONG_SECRET_KEY_AT_LEAST_32_CHARS_123456!"
}
}
FAQ
1. Should I use JWT or Cookie authentication?
| Scenario | Recommendation |
|---|---|
| Web API (mobile/SPA clients) | JWT |
| Razor Pages / MVC (server-side) | Cookie |
| Microservices | JWT |
| Internal admin tools | Cookie + IP filtering |
2. How do I refresh expired tokens?
Implement refresh token logic in your token service:
[HttpPost("refresh")]
public IActionResult RefreshToken([FromBody] string refreshToken)
{
var user = ValidateRefreshToken(refreshToken);
if (user == null) return Unauthorized();
var newToken = _tokenService.BuildToken(user);
return Ok(new { Token = newToken });
}
3. Can I use both JWT and Cookie auth in the same app?
Yes! Use JWT for API endpoints and Cookie for Razor Pages:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => { /* JWT config */ })
.AddCookie(options => { /* Cookie config */ });
// Apply [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
// to API controllers
4. Is MD5 secure for password hashing?
No! MD5 is deprecated. Use:
- BCrypt (recommended):
BCrypt.Net.HashPassword(password) - ASP.NET Core Identity (built-in): Handles hashing + salting automatically
Related CHD Packages
| Package | Description | NuGet |
|---|---|---|
| Chd.Common | Infrastructure primitives (encryption, config, extensions) | NuGet |
| Chd.Min.IO | MinIO/S3 object storage with image optimization | NuGet |
| Chd.Logging | Structured logging with Serilog (Graylog, MSSQL, file sinks) | NuGet |
| Chd.Caching | Redis distributed caching with AOP attributes | NuGet |
Contributing π€
Found a security vulnerability? Please do not open a public issue. Email security@chd.dev instead.
For feature requests:
- Issues: GitHub Issues
- Pull Requests: GitHub PRs
Authors
- Mehmet YoldaΕ (LinkedIn)
See also contributors on NuGet
License π
This package is free and open-source under the MIT License.
Made with β€οΈ by the CHD Team
Cleverly Handle Difficulty π
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Chd.Library.Common (>= 8.6.0)
- GSS.Authentication.CAS.AspNetCore (>= 5.3.3)
- Microsoft.AspNetCore (>= 2.2.0)
- Microsoft.AspNetCore.Authentication (>= 2.2.0)
- Microsoft.AspNetCore.Authentication.Abstractions (>= 2.2.0)
- Microsoft.AspNetCore.Authentication.Cookies (>= 2.2.0)
- Microsoft.AspNetCore.Authentication.Core (>= 2.2.0)
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 8.0.1)
- Microsoft.AspNetCore.Authorization.Policy (>= 2.2.0)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.2.0)
- Microsoft.AspNetCore.Http.Extensions (>= 2.2.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.1)
- Microsoft.Extensions.Configuration.FileExtensions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Json (>= 8.0.0)
- Microsoft.Extensions.FileProviders.Abstractions (>= 8.0.0)
- Microsoft.Extensions.FileProviders.Physical (>= 8.0.0)
- Microsoft.Extensions.FileSystemGlobbing (>= 8.0.0)
- Microsoft.Extensions.Primitives (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.