using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Security.Cryptography; using System.Text; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; using MotoresArgentinosV2.Core.Entities; using MotoresArgentinosV2.Core.Interfaces; using OtpNet; namespace MotoresArgentinosV2.Infrastructure.Services; public class TokenService : ITokenService { private readonly IConfiguration _config; public TokenService(IConfiguration config) { _config = config; } public string GenerateJwtToken(User user) { var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(_config["Jwt:Key"] ?? "SUPER_SECRET_KEY_FOR_MOTORES_ARGENTINOS_V2_2026"); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, user.UserID.ToString()), new Claim(ClaimTypes.Name, user.UserName), new Claim(ClaimTypes.Email, user.Email), new Claim(ClaimTypes.Role, user.UserType == 3 ? "Admin" : "User") }), Expires = DateTime.UtcNow.AddHours(8), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature), Issuer = _config["Jwt:Issuer"], Audience = _config["Jwt:Audience"] }; var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); } public RefreshToken GenerateRefreshToken(string ipAddress) { var refreshToken = new RefreshToken { Token = Convert.ToHexString(RandomNumberGenerator.GetBytes(64)), Expires = DateTime.UtcNow.AddDays(7), // Dura 7 días Created = DateTime.UtcNow, CreatedByIp = ipAddress }; return refreshToken; } public string GenerateMFACode() { var random = new Random(); return random.Next(100000, 999999).ToString(); } public string GenerateBase32Secret() { var key = KeyGeneration.GenerateRandomKey(20); return Base32Encoding.ToString(key); } public string GetQrCodeUri(string userEmail, string secret) { return $"otpauth://totp/MotoresV2:{userEmail}?secret={secret}&issuer=MotoresArgentinosV2"; } public bool ValidateTOTP(string secret, string code) { try { var bytes = Base32Encoding.ToBytes(secret); var totp = new Totp(bytes); return totp.VerifyTotp(code, out _, new VerificationWindow(1, 1)); } catch { return false; } } }