Azimzada.JwtHelper
1.0.0
dotnet add package Azimzada.JwtHelper --version 1.0.0
NuGet\Install-Package Azimzada.JwtHelper -Version 1.0.0
<PackageReference Include="Azimzada.JwtHelper" Version="1.0.0" />
<PackageVersion Include="Azimzada.JwtHelper" Version="1.0.0" />
<PackageReference Include="Azimzada.JwtHelper" />
paket add Azimzada.JwtHelper --version 1.0.0
#r "nuget: Azimzada.JwtHelper, 1.0.0"
#:package Azimzada.JwtHelper@1.0.0
#addin nuget:?package=Azimzada.JwtHelper&version=1.0.0
#tool nuget:?package=Azimzada.JwtHelper&version=1.0.0
Azimzada.JwtHelper
A lightweight, flexible and production-ready JWT helper library for .NET.
Features
✨ Multiple Algorithm Support
- HS256, HS384, HS512 (HMAC)
- RS256 (RSA)
🔐 Comprehensive Token Management
- Easy token generation
- Robust token validation
- Refresh token support
- Claim extraction and management
🎯 Clean Architecture
- Fluent API design
- Built-in Dependency Injection
- Minimal external dependencies
- Null-safe operations
📊 Production-Ready
- XML documentation
- Comprehensive error handling
- Performance optimized
- Thread-safe operations
Installation
Via NuGet Package Manager
Install-Package Azimzada.JwtHelper
Via .NET CLI
dotnet add package Azimzada.JwtHelper
Via Package Reference
<PackageReference Include="Azimzada.JwtHelper" Version="1.0.0" />
Quick Start
1. Configuration
Option A: Using appsettings.json
{
"JwtOptions": {
"Issuer": "https://example.com",
"Audience": "example-api",
"SecretKey": "your-super-secret-key-min-32-chars-long!",
"ExpirationMinutes": 60,
"RefreshTokenExpirationDays": 7
}
}
Option B: Direct Configuration
services.AddJwtHelper(options =>
{
options.Issuer = "https://example.com";
options.Audience = "example-api";
options.SecretKey = "your-super-secret-key-min-32-chars-long!";
options.ExpirationMinutes = 60;
options.RefreshTokenExpirationDays = 7;
});
2. Dependency Injection Setup
Add to your Program.cs or Startup.cs:
// Using configuration
services.AddJwtHelper(configuration);
// Or using action
services.AddJwtHelper(options =>
{
options.Issuer = "https://myapp.com";
options.Audience = "myapp-users";
options.SecretKey = "your-secret-key-here";
});
3. Token Generation
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly JwtBuilder _jwtBuilder;
public AuthController(JwtBuilder jwtBuilder)
{
_jwtBuilder = jwtBuilder;
}
[HttpPost("login")]
public IActionResult Login(LoginRequest request)
{
// Validate user credentials...
// Generate token with custom claims
var jwtResult = _jwtBuilder
.AddClaim(JwtClaimNames.UserId, userId)
.AddClaim(JwtClaimNames.Username, request.Username)
.AddClaim(JwtClaimNames.Role, "Admin")
.AddClaim("custom-claim", "custom-value")
.BuildHS256(userId);
return Ok(new
{
accessToken = jwtResult.Token,
refreshToken = jwtResult.RefreshToken,
expiresAt = jwtResult.ExpiresAt,
tokenType = jwtResult.TokenType
});
}
}
4. Token Validation
[ApiController]
[Route("api/[controller]")]
public class ProtectedController : ControllerBase
{
private readonly JwtValidator _jwtValidator;
public ProtectedController(JwtValidator jwtValidator)
{
_jwtValidator = jwtValidator;
}
[HttpGet("protected-endpoint")]
public IActionResult GetProtected()
{
var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
if (!_jwtValidator.ValidateHS256(token))
return Unauthorized("Invalid or expired token");
var userId = _jwtValidator.GetClaimValue(token, JwtClaimNames.UserId);
var username = _jwtValidator.GetClaimValue(token, JwtClaimNames.Username);
return Ok(new
{
message = $"Hello, {username}!",
userId = userId
});
}
}
Advanced Usage
Adding Multiple Claims
var claims = new Dictionary<string, object>
{
{ JwtClaimNames.UserId, "12345" },
{ JwtClaimNames.Username, "john_doe" },
{ JwtClaimNames.Role, "Admin" },
{ "department", "Engineering" },
{ "level", 5 }
};
var result = _jwtBuilder
.AddClaims(claims)
.BuildHS256("user123");
Using RS256 (RSA)
// Configure with RSA keys
services.AddJwtHelper(options =>
{
options.Issuer = "https://myapp.com";
options.Audience = "myapp-users";
options.PrivateKey = rsaPrivateKeyPem; // PEM format
options.PublicKey = rsaPublicKeyPem; // PEM format
});
// Generate RS256 token
var result = _jwtBuilder
.AddClaim(JwtClaimNames.UserId, userId)
.AddClaim(JwtClaimNames.Role, "User")
.BuildRS256(userId);
// Validate RS256 token
if (_jwtValidator.ValidateRS256(token))
{
// Token is valid
}
Extracting Claims
// Extract all claims without validation (use only if you trust the source)
var allClaims = _jwtValidator.ExtractClaims(token);
// Get specific claim value
var userId = _jwtValidator.GetClaimValue(token, JwtClaimNames.UserId);
// Check token expiration
if (_jwtValidator.IsTokenExpired(token))
{
// Token has expired
}
// Get exact expiration date
var expiresAt = _jwtValidator.GetTokenExpiration(token);
Method Chaining (Fluent API)
var result = _jwtBuilder
.AddClaim(JwtClaimNames.UserId, "user-123")
.AddClaim(JwtClaimNames.Username, "john")
.AddClaim(JwtClaimNames.Role, "Admin")
.AddClaim("department", "IT")
.AddClaim("level", 5)
.BuildHS256("user-123");
// For next token, clear claims
_jwtBuilder.ClearClaims();
var anotherResult = _jwtBuilder
.AddClaim(JwtClaimNames.UserId, "user-456")
.BuildHS256("user-456");
Claim Names
The library provides standard claim names:
JwtClaimNames.UserId // "uid"
JwtClaimNames.Username // "uname"
JwtClaimNames.Role // "role"
JwtClaimNames.Email // "email"
JwtClaimNames.FullName // "fullname"
You can also use custom claim names with AddClaim() method.
Sample Token Decode
Input
var result = _jwtBuilder
.AddClaim(JwtClaimNames.UserId, "12345")
.AddClaim(JwtClaimNames.Username, "john_doe")
.AddClaim(JwtClaimNames.Role, "Admin")
.BuildHS256("12345");
var token = result.Token;
Decoded Output (Header.Payload.Signature)
Header:
{
"alg": "HS256",
"typ": "JWT"
}
Payload:
{
"uid": "12345",
"uname": "john_doe",
"role": "Admin",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "12345",
"sub": "12345",
"jti": "550e8400-e29b-41d4-a716-446655440000",
"iss": "https://example.com",
"aud": "example-api",
"exp": 1700000000,
"iat": 1699999000,
"nbf": 1699999000
}
.NET Target Frameworks
The package supports:
- ✅ .NET 6.0
- ✅ .NET 7.0
- ✅ .NET 8.0
- ✅ .NET 9.0
- ✅ .NET Standard 2.0
This ensures compatibility with:
- Modern .NET applications
- Legacy .NET Framework projects
- Shared libraries and NuGet packages
API Reference
JwtBuilder
| Method | Description |
|---|---|
AddClaim(key, value) |
Add a single custom claim |
AddClaims(claims) |
Add multiple claims |
BuildHS256(subject) |
Generate HS256 token |
BuildHS384(subject) |
Generate HS384 token |
BuildHS512(subject) |
Generate HS512 token |
BuildRS256(subject) |
Generate RS256 token |
GenerateRefreshToken() |
Generate refresh token |
ClearClaims() |
Clear all added claims |
JwtValidator
| Method | Description |
|---|---|
ValidateHS256(token) |
Validate HS256 token |
ValidateHS384(token) |
Validate HS384 token |
ValidateHS512(token) |
Validate HS512 token |
ValidateRS256(token) |
Validate RS256 token |
ExtractClaims(token) |
Extract all claims |
GetClaimValue(token, claimType) |
Get specific claim |
IsTokenExpired(token) |
Check if expired |
GetTokenExpiration(token) |
Get expiration date |
Security Tips
🔒 Secret Key Management
// ❌ Don't hardcode secrets
var options = new JwtOptions
{
SecretKey = "hardcoded-secret" // Bad!
};
// ✅ Use configuration and environment variables
var secretKey = configuration["JwtOptions:SecretKey"]; // Good!
var secretKey = Environment.GetEnvironmentVariable("JWT_SECRET_KEY"); // Better!
🔐 Key Length Requirements
- HS256: Minimum 32 bytes (256 bits)
- HS384: Minimum 48 bytes (384 bits)
- HS512: Minimum 64 bytes (512 bits)
// Generate secure key
var secureKey = new byte[64]; // 512 bits
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(secureKey);
}
var secretKeyString = Convert.ToBase64String(secureKey);
🛡️ Best Practices
- Always use HTTPS for token transmission
- Store tokens securely in client applications
- Set appropriate expiration times (60-120 minutes for access tokens)
- Use refresh tokens for extending sessions
- Validate tokens on every protected endpoint
- Log authentication failures for security audits
- Rotate secrets regularly
License
This project is licensed under the MIT License - see the LICENSE file for details.
Author
Mahammad Azimzada
Support
For issues, questions, or contributions, please visit:
- GitHub: https://github.com/MrAzimzadeh/JwtHelper
- NuGet: https://www.nuget.org/packages/Azimzada.JwtHelper
Made with ❤️ for the .NET community
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 is compatible. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.IdentityModel.Tokens (>= 7.0.0)
- System.IdentityModel.Tokens.Jwt (>= 7.0.0)
-
net6.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.IdentityModel.Tokens (>= 7.0.0)
- System.IdentityModel.Tokens.Jwt (>= 7.0.0)
-
net7.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.IdentityModel.Tokens (>= 7.0.0)
- System.IdentityModel.Tokens.Jwt (>= 7.0.0)
-
net8.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.IdentityModel.Tokens (>= 7.0.0)
- System.IdentityModel.Tokens.Jwt (>= 7.0.0)
-
net9.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.IdentityModel.Tokens (>= 7.0.0)
- System.IdentityModel.Tokens.Jwt (>= 7.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.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 207 | 11/27/2025 |
Initial release with HS256, HS384, HS512 and RS256 support.