improvement: 로그인 분기 계약 확장 (#177)

- LoginResponseDto에 nextAction, emailVerified, verifySessionId, emailSent 추가
- 미인증 유저 로그인 시 verify session/인증코드 생성 + 메일 발송
- Swagger Description에 분기 설명 추가

Closes #177
This commit is contained in:
SEAN 2026-02-25 10:08:45 +09:00
parent 512585e7e7
commit 859eabd83c
3 changed files with 55 additions and 2 deletions

View File

@ -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<LoginResponseDto>))]
[SwaggerResponse(401, "로그인 실패")]
public async Task<IActionResult> LoginAsync([FromBody] LoginRequestDto request)

View File

@ -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; }
}

View File

@ -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,