using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Security.Cryptography; using System.Text; using Back.Program.Common.Model; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; namespace Back.Program.Common.Auth { /// /// 사용자의 정보를 바탕으로 JWT 생성 /// public class JwtTokenService { private readonly JwtSettings _jwtSettings; private readonly ILogger _logger; public JwtTokenService(IOptions jwtSettings, ILogger logger) { _jwtSettings = jwtSettings.Value; _logger = logger; } // JWT 토큰 생성 public string GenerateJwtToken(string jwtKey)//, string role) { // 1. 클레임(Claim) 설정 - 필요에 따라 추가 정보도 포함 var claims = new List { // 토큰 주체(sub) 생성을 위해 값으로 uid를 사용함 : 토큰이 대표하는 고유 식별자 new Claim(JwtRegisteredClaimNames.Sub, jwtKey), // Jti 는 토큰 식별자로 토큰의 고유 ID 이다. new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), // jwt 토큰이 가지는 권한 // new Claim(ClaimTypes.Role, role), // 추가 클레임 예: new Claim(ClaimTypes.Role, "Admin") }; // 2. 비밀 키와 SigningCredentials 생성 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey)); var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); // 3. 토큰 생성 (Issuer, Audience, 만료 시간, 클레임, 서명 정보 포함) var token = new JwtSecurityToken( issuer: _jwtSettings.Issuer, audience: _jwtSettings.Audience, claims: claims, expires: DateTime.Now.AddMinutes(_jwtSettings.ExpiryMinutes), signingCredentials: credentials ); // 4. 토큰 객체를 문자열로 변환하여 반환 return new JwtSecurityTokenHandler().WriteToken(token); } // 리프레시 토큰 생성 public RefreshToken GenerateRefreshToken(string uid) { var randomNumber = new byte[32]; // 256비트 using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(randomNumber); } return new RefreshToken() { uid = uid, refresh_token = Convert.ToBase64String(randomNumber), create_Date = DateTime.UtcNow, expire_date = DateTime.UtcNow.AddDays(_jwtSettings.RefreshTokenExpiryDays) }; } /// /// 여기는 엑세스 토큰의 확인을 위한 jwt 서비스 내의 인증 메서드 /// public async Task ValidateToken(string token) { if (string.IsNullOrWhiteSpace(token)) return null; var tokenHandler = new JwtSecurityTokenHandler(); try { var key = Encoding.UTF8.GetBytes(_jwtSettings.SecretKey); var validationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(key), ValidateIssuer = true, ValidIssuer = _jwtSettings.Issuer, ValidateAudience = true, ValidAudience = _jwtSettings.Audience, ValidateLifetime = true, ClockSkew = TimeSpan.FromMinutes(_jwtSettings.ClockSkewMinutes) }; var principal = tokenHandler.ValidateToken(token, validationParameters, out var securityToken); return principal; } catch (Exception ex) { _logger.LogError($"엑세스 토큰 오류: {ex.Message}"); return null; } } } }