From 71102e38acbb5f85877889f9cead1f0434b9786c Mon Sep 17 00:00:00 2001 From: SEAN Date: Thu, 26 Feb 2026 10:11:26 +0900 Subject: [PATCH] =?UTF-8?q?improvement:=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EC=9D=91=EB=8B=B5=20=ED=91=9C=EC=A4=80=ED=99=94=20?= =?UTF-8?q?=EB=B0=8F=20=EB=8B=A8=EC=9D=BC=20API=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=20(#253)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LogoutResponseDto 신규 (logged_out, redirect_to 힌트) - LogoutAsync 반환 타입 Task → Task - AuthController Swagger 문서에 설정 화면 단일 API 사용 명시 Closes #253 --- SPMS.API/Controllers/AuthController.cs | 9 +++++---- SPMS.Application/DTOs/Auth/LogoutResponseDto.cs | 12 ++++++++++++ SPMS.Application/Interfaces/IAuthService.cs | 2 +- SPMS.Application/Services/AuthService.cs | 8 +++++++- 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 SPMS.Application/DTOs/Auth/LogoutResponseDto.cs diff --git a/SPMS.API/Controllers/AuthController.cs b/SPMS.API/Controllers/AuthController.cs index fdc41e0..7d6afd3 100644 --- a/SPMS.API/Controllers/AuthController.cs +++ b/SPMS.API/Controllers/AuthController.cs @@ -82,8 +82,9 @@ public class AuthController : ControllerBase [Authorize] [SwaggerOperation( Summary = "로그아웃", - Description = "현재 로그인된 관리자의 토큰을 무효화합니다. Refresh Token은 DB에서 삭제되고, Access Token은 Redis 블랙리스트에 등록되어 즉시 사용 불가합니다.")] - [SwaggerResponse(200, "로그아웃 성공")] + Description = "현재 로그인된 관리자의 토큰을 무효화합니다. Refresh Token은 DB에서 삭제되고, Access Token은 Redis 블랙리스트에 등록되어 즉시 사용 불가합니다. " + + "설정/마이페이지/프로필 등 모든 화면에서 이 단일 API를 사용합니다. 응답의 redirect_to로 이동합니다.")] + [SwaggerResponse(200, "로그아웃 성공", typeof(ApiResponse))] [SwaggerResponse(401, "인증되지 않은 요청")] public async Task LogoutAsync() { @@ -94,8 +95,8 @@ public class AuthController : ControllerBase var accessToken = HttpContext.Request.Headers["Authorization"] .ToString().Replace("Bearer ", ""); - await _authService.LogoutAsync(adminId, accessToken); - return Ok(ApiResponse.Success()); + var result = await _authService.LogoutAsync(adminId, accessToken); + return Ok(ApiResponse.Success(result)); } [HttpPost("email/verify")] diff --git a/SPMS.Application/DTOs/Auth/LogoutResponseDto.cs b/SPMS.Application/DTOs/Auth/LogoutResponseDto.cs new file mode 100644 index 0000000..61cf46c --- /dev/null +++ b/SPMS.Application/DTOs/Auth/LogoutResponseDto.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace SPMS.Application.DTOs.Auth; + +public class LogoutResponseDto +{ + [JsonPropertyName("logged_out")] + public bool LoggedOut { get; set; } + + [JsonPropertyName("redirect_to")] + public string RedirectTo { get; set; } = "/login"; +} diff --git a/SPMS.Application/Interfaces/IAuthService.cs b/SPMS.Application/Interfaces/IAuthService.cs index a41299a..5c75d27 100644 --- a/SPMS.Application/Interfaces/IAuthService.cs +++ b/SPMS.Application/Interfaces/IAuthService.cs @@ -8,7 +8,7 @@ public interface IAuthService Task SignupAsync(SignupRequestDto request); Task LoginAsync(LoginRequestDto request); Task RefreshTokenAsync(TokenRefreshRequestDto request); - Task LogoutAsync(long adminId, string accessToken); + Task LogoutAsync(long adminId, string accessToken); Task ChangePasswordAsync(long adminId, ChangePasswordRequestDto request); Task CheckEmailAsync(EmailCheckRequestDto request); Task VerifyEmailAsync(EmailVerifyRequestDto request); diff --git a/SPMS.Application/Services/AuthService.cs b/SPMS.Application/Services/AuthService.cs index cb82514..44ac0e6 100644 --- a/SPMS.Application/Services/AuthService.cs +++ b/SPMS.Application/Services/AuthService.cs @@ -287,7 +287,7 @@ public class AuthService : IAuthService }; } - public async Task LogoutAsync(long adminId, string accessToken) + public async Task LogoutAsync(long adminId, string accessToken) { // 1. 관리자 조회 var admin = await _adminRepository.GetByIdAsync(adminId); @@ -313,6 +313,12 @@ public class AuthService : IAuthService if (remaining > TimeSpan.Zero) await _tokenStore.StoreAsync($"blacklist:{jti}", "revoked", remaining); } + + return new LogoutResponseDto + { + LoggedOut = true, + RedirectTo = "/login" + }; } public async Task ChangePasswordAsync(long adminId, ChangePasswordRequestDto request) -- 2.45.1