# EonaCat.SecureToken **Secure, modern token library for .NET with key rotation, signing isolation, validation rules, and .NET Standard support.** EonaCat.SecureToken provides a safer alternative to rolling your own authentication tokens. It focuses on: - Strong cryptographic signing - Versioned key management - Token lifecycle validation - Refresh/access token separation - Extensible claims - API-friendly validation results - `.NET Standard 2.0` compatibility ## Features ### Cryptographic protection - HMAC based token signing - HKDF derived context-specific keys - Constant-time signature verification - Tamper detection - Strong random key generation ### Key rotation Rotate signing keys without invalidating existing tokens. Example: ```csharp var store = SigningKeyStore.CreateNew(); var service = new TokenService(store); var oldToken = service.Issue( TokenDescriptor.Create() .ForSubject("user-123") .IssuedBy("my-api") .ForAudience("mobile") ); // Rotate keys store.Rotate(); // New tokens use the new key var newToken = service.Issue( TokenDescriptor.Create() .ForSubject("user-456") .IssuedBy("my-api") .ForAudience("mobile") ); // Old token still validates service.Validate( oldToken, TokenValidationOptions.AccessToken("my-api", "mobile") ); ``` ## Installation Install from NuGet: ```bash dotnet add package EonaCat.SecureToken ``` # Quick Start ## Create a token service ```csharp using EonaCat.SecureToken.Core; using EonaCat.SecureToken.Cryptography; var keys = SigningKeyStore.CreateNew(); var tokens = new TokenService(keys); ``` ## Issue an access token ```csharp var token = tokens.Issue( TokenDescriptor.Create() .ForSubject("user-123") .IssuedBy("my-service") .ForAudience("api") .WithRole("admin") .WithClaim("email", "user@example.com") ); ``` The token contains: - Subject - Issuer - Audience - Roles - Custom claims - Token ID - Expiration - Key generation information ## Validate a token ```csharp var result = tokens.Validate( token, TokenValidationOptions.AccessToken( issuer: "my-service", audience: "api" ) ); if (result.IsSuccess) { var claims = result.UnwrapClaims(); Console.WriteLine(claims.Subject); } ``` # Token expiration ```csharp var token = tokens.Issue( TokenDescriptor.Create() .ForSubject("user-1") .IssuedBy("api") .ForAudience("mobile") .WithLifetime(TimeSpan.FromMinutes(15)) ); ``` Expired tokens are automatically rejected. # Refresh tokens Create a refresh token: ```csharp var pair = tokens.IssueTokenPair( "user-1", "api", "mobile" ); Console.WriteLine(pair.AccessToken); Console.WriteLine(pair.RefreshToken); ``` Validate separately: ```csharp tokens.Validate( pair.RefreshToken, TokenValidationOptions.RefreshToken("api") ); ``` Refresh tokens cannot be used as access tokens. # Token binding Bind tokens to a context such as a device or session: ```csharp var token = tokens.Issue( TokenDescriptor.Create() .ForSubject("user-1") .IssuedBy("api") .ForAudience("web") .BoundTo("device-identifier") ); ``` Validation: ```csharp new TokenValidationOptions { ValidIssuer = "api", ValidAudience = "web", BindingContext = "device-identifier" }; ``` # Revocation You can integrate your own revocation storage: ```csharp var options = new TokenValidationOptions { ValidIssuer = "api", ValidAudience = "web", RevocationCheck = async (tokenId, cancellationToken) => { return await database.IsRevoked(tokenId); } }; ``` # ASP.NET Core dependency injection ```csharp builder.Services.AddSecureTokens(); ``` or provide your own key store: ```csharp builder.Services.AddSecureTokens( store => { return SigningKeyStore.FromKeys( new[] { (1, secretKeyBytes) }); }); ``` # Security design The library separates cryptographic purposes: ``` Master Key | +-- Signing Key | +-- Encryption Key | +-- Context-specific keys ``` This prevents accidental key reuse between operations. # Supported frameworks - .NET Standard 2.0 - .NET Standard 2.1 - .NET Framework 4.8 - .NET 8+ # When to use Good fit for: APIs Microservices Internal authentication Service-to-service tokens Applications needing key rotation # When not to use Do not store secrets directly in source code. Use: - Environment variables - Secret managers - Hardware-backed key storage where required # License Apache License.