using System.Security.Cryptography; using System.Text; using System.Text.Json; namespace API.Services; public class TokenService : ITokenService { private readonly byte[] _secretKey; public TokenService(IConfiguration? configuration = null) { var secret = configuration?["Jwt:Secret"] ?? "ChronoCCG_Super_Secret_Key_For_Jwt_Authentication_2026_Long_Key!"; _secretKey = Encoding.UTF8.GetBytes(secret); } public string GenerateToken(string username) { var payload = new TokenPayload { Username = username, ExpiresAt = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds() }; var json = JsonSerializer.Serialize(payload); var payloadBytes = Encoding.UTF8.GetBytes(json); var payloadBase64 = Convert.ToBase64String(payloadBytes); using var hmac = new HMACSHA256(_secretKey); var sigBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(payloadBase64)); var sigBase64 = Convert.ToBase64String(sigBytes); return $"{payloadBase64}.{sigBase64}"; } public string? ValidateToken(string? token) { if (string.IsNullOrWhiteSpace(token)) return null; var parts = token.Split('.'); if (parts.Length != 2) return null; var payloadBase64 = parts[0]; var sigBase64 = parts[1]; using var hmac = new HMACSHA256(_secretKey); var expectedSigBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(payloadBase64)); var expectedSigBase64 = Convert.ToBase64String(expectedSigBytes); if (sigBase64 != expectedSigBase64) return null; try { var payloadBytes = Convert.FromBase64String(payloadBase64); var json = Encoding.UTF8.GetString(payloadBytes); var payload = JsonSerializer.Deserialize(json); if (payload == null || string.IsNullOrWhiteSpace(payload.Username)) return null; if (DateTimeOffset.UtcNow.ToUnixTimeSeconds() > payload.ExpiresAt) return null; return payload.Username; } catch { return null; } } private class TokenPayload { public string Username { get; set; } = string.Empty; public long ExpiresAt { get; set; } } }