using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using HelpDesk.Models.Enums; using Microsoft.IdentityModel.Tokens; namespace HelpDesk.API.Services; public class JwtService : IJwtService { private readonly IConfiguration _configuration; public JwtService(IConfiguration configuration) { _configuration = configuration; } public string GenerateToken(Guid userId, string email, UserRole role) { var secretKey = _configuration["JwtSettings:SecretKey"] ?? throw new InvalidOperationException("JWT SecretKey is not configured."); var issuer = _configuration["JwtSettings:Issuer"] ?? "HelpDesk"; var audience = _configuration["JwtSettings:Audience"] ?? "HelpDeskAPI"; var expiryMinutes = int.TryParse(_configuration["JwtSettings:ExpiryMinutes"], out var minutes) ? minutes : 60; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey)); var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var claims = new[] { new Claim(JwtRegisteredClaimNames.Sub, userId.ToString()), new Claim(JwtRegisteredClaimNames.Email, email), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(ClaimTypes.Role, role.ToString()), new Claim("userId", userId.ToString()) }; var token = new JwtSecurityToken( issuer: issuer, audience: audience, claims: claims, expires: DateTime.UtcNow.AddMinutes(expiryMinutes), signingCredentials: credentials ); return new JwtSecurityTokenHandler().WriteToken(token); } public ClaimsPrincipal? ValidateToken(string token) { var secretKey = _configuration["JwtSettings:SecretKey"] ?? throw new InvalidOperationException("JWT SecretKey is not configured."); var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.UTF8.GetBytes(secretKey); try { var principal = tokenHandler.ValidateToken(token, new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = _configuration["JwtSettings:Issuer"], ValidAudience = _configuration["JwtSettings:Audience"], IssuerSigningKey = new SymmetricSecurityKey(key), ClockSkew = TimeSpan.Zero }, out _); return principal; } catch { return null; } } }