From bbbaaed608da3eb40e6a2b0c26c72e33dd6c2a67 Mon Sep 17 00:00:00 2001 From: GoGradually Date: Sat, 27 Dec 2025 18:01:21 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infrastructure/jwt/TokenCookieFactory.java | 14 ++++++++++++-- .../interfaces/member/MemberController.java | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/gg/pinit/infrastructure/jwt/TokenCookieFactory.java b/src/main/java/me/gg/pinit/infrastructure/jwt/TokenCookieFactory.java index e6313a1..2e2670c 100644 --- a/src/main/java/me/gg/pinit/infrastructure/jwt/TokenCookieFactory.java +++ b/src/main/java/me/gg/pinit/infrastructure/jwt/TokenCookieFactory.java @@ -17,7 +17,17 @@ public TokenCookieFactory(CookieProperties cookieProperties) { } public ResponseCookie refreshTokenCookie(String refreshToken) { - ResponseCookie.ResponseCookieBuilder builder = ResponseCookie.from("refresh_token", refreshToken) + return refreshTokenCookieBuilder(refreshToken).build(); + } + + public ResponseCookie deleteRefreshTokenCookie() { + return refreshTokenCookieBuilder("") + .maxAge(0) + .build(); + } + + private ResponseCookie.ResponseCookieBuilder refreshTokenCookieBuilder(String value) { + ResponseCookie.ResponseCookieBuilder builder = ResponseCookie.from("refresh_token", value) .httpOnly(true) .path("/") .secure(cookieProperties.isSecure()); @@ -29,6 +39,6 @@ public ResponseCookie refreshTokenCookie(String refreshToken) { builder.sameSite(cookieProperties.getSameSite()); } - return builder.build(); + return builder; } } diff --git a/src/main/java/me/gg/pinit/interfaces/member/MemberController.java b/src/main/java/me/gg/pinit/interfaces/member/MemberController.java index 8734e75..c4c2fc5 100644 --- a/src/main/java/me/gg/pinit/interfaces/member/MemberController.java +++ b/src/main/java/me/gg/pinit/interfaces/member/MemberController.java @@ -17,6 +17,7 @@ import me.gg.pinit.interfaces.member.dto.LoginResponse; import me.gg.pinit.interfaces.member.dto.SignupRequest; import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -109,6 +110,21 @@ public ResponseEntity refresh(HttpServletRequest request) { .body(new LoginResponse(newAccessToken)); } + @PostMapping("/logout") + @Operation( + summary = "로그아웃", + description = "refresh_token 쿠키를 만료시켜 로그아웃 처리합니다." + ) + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "로그아웃 성공") + }) + public ResponseEntity logout() { + ResponseCookie expiredCookie = tokenCookieFactory.deleteRefreshTokenCookie(); + return ResponseEntity.ok() + .header(HttpHeaders.SET_COOKIE, expiredCookie.toString()) + .build(); + } + @GetMapping("/me") @Operation( summary = "로그인 확인",