using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using UserMicroservice.Models; using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore; namespace UserMicroservice.Services { public class AuthService : IAuthService { private readonly IConfiguration _configuration; private readonly ApplicationDbContext _context; public AuthService(IConfiguration configuration, ApplicationDbContext applicationDbContext) { _configuration = configuration; _context = applicationDbContext; } public AuthTokenPair AuthenticateUser(int userId) { string accessToken = GenerateAccessToken(userId); string refreshToken = GenerateRefreshToken(userId).Token; return new AuthTokenPair(accessToken, refreshToken); } private string GenerateAccessToken(int userId) { string? configuredKey = _configuration["Jwt:Key"]; string? configuredIssuer = _configuration["Jwt:Issuer"]; string? configuredAudience = _configuration["Jwt:Audience"]; throwIfNull(configuredKey, configuredIssuer, configuredAudience); var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuredKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var claims = new List<Claim> { new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(ClaimTypes.NameIdentifier, userId.ToString()), }; var token = new JwtSecurityToken( issuer: configuredIssuer, audience: configuredAudience, claims: claims, expires: DateTime.UtcNow.AddMinutes(30), signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); } private RefreshToken GenerateRefreshToken(int userId) { RefreshToken refreshToken = new(Guid.NewGuid().ToString(), DateTime.UtcNow.AddDays(2), userId); _context.RefreshTokens.Add(refreshToken); _context.SaveChanges(); return refreshToken; } public bool ValidateRefreshToken(string token) { RefreshToken? refreshToken = _context.RefreshTokens.SingleOrDefault(t => t.Token == token); if (refreshToken != null) { if (DateTime.UtcNow <= refreshToken.ExpirationDate) { return true; } // delete expired token RevokeRefreshToken(token); } return false; } public void RevokeRefreshToken(string token) { _context.RefreshTokens.Where(t => t.Token == token).ExecuteDelete(); _context.SaveChanges(); } private void throwIfNull(string? key, string? issuer, string? audience) { if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(issuer) || string.IsNullOrEmpty(audience)) { throw new ArgumentNullException("JWT configuration is missing."); } } } }