diff --git a/SPMS.API/Controllers/AuthController.cs b/SPMS.API/Controllers/AuthController.cs index 026d674..814d752 100644 --- a/SPMS.API/Controllers/AuthController.cs +++ b/SPMS.API/Controllers/AuthController.cs @@ -51,7 +51,9 @@ public class AuthController : ControllerBase [AllowAnonymous] [SwaggerOperation( Summary = "관리자 로그인", - Description = "이메일과 비밀번호로 로그인하여 JWT 토큰을 발급받습니다.")] + Description = "이메일과 비밀번호로 로그인하여 JWT 토큰을 발급받습니다. " + + "응답의 nextAction으로 화면 분기: GO_DASHBOARD(대시보드), VERIFY_EMAIL(이메일 인증 필요). " + + "미인증 유저는 verifySessionId와 emailSent가 함께 반환됩니다.")] [SwaggerResponse(200, "로그인 성공", typeof(ApiResponse))] [SwaggerResponse(401, "로그인 실패")] public async Task LoginAsync([FromBody] LoginRequestDto request) diff --git a/SPMS.Application/DTOs/Auth/LoginResponseDto.cs b/SPMS.Application/DTOs/Auth/LoginResponseDto.cs index c5e8b51..0738fc5 100644 --- a/SPMS.Application/DTOs/Auth/LoginResponseDto.cs +++ b/SPMS.Application/DTOs/Auth/LoginResponseDto.cs @@ -13,6 +13,18 @@ public class LoginResponseDto [JsonPropertyName("expires_in")] public int ExpiresIn { get; set; } + [JsonPropertyName("next_action")] + public string NextAction { get; set; } = string.Empty; + + [JsonPropertyName("email_verified")] + public bool EmailVerified { get; set; } + + [JsonPropertyName("verify_session_id")] + public string? VerifySessionId { get; set; } + + [JsonPropertyName("email_sent")] + public bool? EmailSent { get; set; } + [JsonPropertyName("admin")] public AdminInfoDto? Admin { get; set; } } diff --git a/SPMS.Application/Services/AuthService.cs b/SPMS.Application/Services/AuthService.cs index b08e535..9c509cc 100644 --- a/SPMS.Application/Services/AuthService.cs +++ b/SPMS.Application/Services/AuthService.cs @@ -155,12 +155,51 @@ public class AuthService : IAuthService _adminRepository.Update(admin); await _unitOfWork.SaveChangesAsync(); - // 6. 응답 반환 + // 6. 분기 판정 + verify session 생성 + var nextAction = "GO_DASHBOARD"; + string? verifySessionId = null; + bool? emailSent = null; + + if (!admin.EmailVerified) + { + nextAction = "VERIFY_EMAIL"; + + // 인증코드 생성/저장 + var verificationCode = Random.Shared.Next(100000, 999999).ToString(); + await _tokenStore.StoreAsync( + $"email_verify:{admin.Email}", + verificationCode, + TimeSpan.FromHours(1)); + + // Verify Session 생성 + verifySessionId = Guid.NewGuid().ToString("N"); + await _tokenStore.StoreAsync( + $"verify_session:{verifySessionId}", + admin.Email, + TimeSpan.FromHours(1)); + + // 메일 발송 (실패해도 로그인은 유지) + emailSent = true; + try + { + await _emailService.SendVerificationCodeAsync(admin.Email, verificationCode); + } + catch + { + emailSent = false; + } + } + + // 7. 응답 반환 return new LoginResponseDto { AccessToken = accessToken, RefreshToken = refreshToken, ExpiresIn = _jwtSettings.ExpiryMinutes * 60, + NextAction = nextAction, + EmailVerified = admin.EmailVerified, + VerifySessionId = verifySessionId, + EmailSent = emailSent, Admin = new AdminInfoDto { AdminCode = admin.AdminCode,