diff --git a/src/main/java/com/doubleo/adminservice/domain/auth/controller/AuthController.java b/src/main/java/com/doubleo/adminservice/domain/auth/controller/AuthController.java index 769533a..7fac82a 100644 --- a/src/main/java/com/doubleo/adminservice/domain/auth/controller/AuthController.java +++ b/src/main/java/com/doubleo/adminservice/domain/auth/controller/AuthController.java @@ -1,18 +1,19 @@ package com.doubleo.adminservice.domain.auth.controller; -import com.doubleo.adminservice.domain.auth.dto.AccessTokenDto; import com.doubleo.adminservice.domain.auth.dto.RefreshTokenDto; import com.doubleo.adminservice.domain.auth.dto.request.LoginRequest; import com.doubleo.adminservice.domain.auth.dto.response.LoginResponse; import com.doubleo.adminservice.domain.auth.service.AuthService; import com.doubleo.adminservice.domain.auth.service.JwtTokenService; import com.doubleo.adminservice.global.util.CookieUtil; +import com.doubleo.adminservice.global.util.JwtUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseCookie; @@ -20,6 +21,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.util.WebUtils; +@Slf4j @Tag(name = "1-2. Auth API", description = "관리자 로그인/로그아웃/Refresh Token 관련 API") @RestController @RequiredArgsConstructor @@ -29,6 +31,7 @@ public class AuthController { private final AuthService authService; private final CookieUtil cookieUtil; private final JwtTokenService jwtTokenService; + private final JwtUtil jwtUtil; @Operation(summary = "관리자 로그인", description = "관리자 로그인을 처리합니다.") @PostMapping("/login") @@ -67,31 +70,30 @@ public ResponseEntity adminLogout( @PostMapping("/reissue") public ResponseEntity tokenReissue( HttpServletRequest request, HttpServletResponse response) { - String oldAccessToken = extractAccessTokenFromHeader(request); + String oldAccessToken = jwtUtil.resolveToken(request.getHeader(HttpHeaders.AUTHORIZATION)); String refreshToken = extractRefreshTokenFromCookie(request); + log.info("oldAccessToken: {}, refreshToken: {}", oldAccessToken, refreshToken); RefreshTokenDto refreshTokenDto = jwtTokenService.retrieveRefreshToken(refreshToken); if (refreshTokenDto == null) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } - AccessTokenDto newAccessTokenDto = - jwtTokenService.reissueAccessTokenIfExpired(oldAccessToken); - response.addHeader( - HttpHeaders.AUTHORIZATION, "Bearer " + newAccessTokenDto.accessTokenValue()); - - return ResponseEntity.ok().build(); + return jwtTokenService + .reissueAccessTokenIfExpired(oldAccessToken) + .map( + newToken -> { + // 새 토큰이 존재할 때 헤더에 담고 200 OK 리턴 + response.setHeader( + HttpHeaders.AUTHORIZATION, + "Bearer " + newToken.accessTokenValue()); + return ResponseEntity.ok().build(); + }) + // 없으면 204 No Content 리턴 + .orElseGet(() -> ResponseEntity.noContent().build()); } private String extractRefreshTokenFromCookie(HttpServletRequest request) { Cookie cookie = WebUtils.getCookie(request, "refreshToken"); return (cookie != null) ? cookie.getValue() : null; } - - private String extractAccessTokenFromHeader(HttpServletRequest request) { - String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION); - if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { - return authorizationHeader.substring(7); - } - return null; - } } diff --git a/src/main/java/com/doubleo/adminservice/domain/auth/service/JwtTokenService.java b/src/main/java/com/doubleo/adminservice/domain/auth/service/JwtTokenService.java index 3ac5888..c7f034a 100644 --- a/src/main/java/com/doubleo/adminservice/domain/auth/service/JwtTokenService.java +++ b/src/main/java/com/doubleo/adminservice/domain/auth/service/JwtTokenService.java @@ -2,6 +2,7 @@ import com.doubleo.adminservice.domain.auth.dto.AccessTokenDto; import com.doubleo.adminservice.domain.auth.dto.RefreshTokenDto; +import java.util.Optional; public interface JwtTokenService { @@ -18,7 +19,7 @@ public interface JwtTokenService { RefreshTokenDto retrieveRefreshToken(String refreshTokenValue); // AccessToken 만료 여부 검증 후 재발급 - AccessTokenDto reissueAccessTokenIfExpired(String accessTokenValue); + Optional reissueAccessTokenIfExpired(String accessTokenValue); // 사용하지 않는 AccessToken BlackList 등록 void putAccessTokenOnBlackList(String accessTokenValue); diff --git a/src/main/java/com/doubleo/adminservice/domain/auth/service/JwtTokenServiceImpl.java b/src/main/java/com/doubleo/adminservice/domain/auth/service/JwtTokenServiceImpl.java index 01e09cf..a5c4daa 100644 --- a/src/main/java/com/doubleo/adminservice/domain/auth/service/JwtTokenServiceImpl.java +++ b/src/main/java/com/doubleo/adminservice/domain/auth/service/JwtTokenServiceImpl.java @@ -10,8 +10,10 @@ import io.jsonwebtoken.ExpiredJwtException; import java.util.Optional; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +@Slf4j @Service @RequiredArgsConstructor public class JwtTokenServiceImpl implements JwtTokenService { @@ -43,7 +45,6 @@ public String createRefreshToken(Long adminId) { public RefreshTokenDto retrieveRefreshToken(String refreshTokenValue) { RefreshTokenDto refreshTokenDto = parseRefreshToken(refreshTokenValue); - if (refreshTokenDto == null) { return null; } @@ -58,14 +59,18 @@ public RefreshTokenDto retrieveRefreshToken(String refreshTokenValue) { return null; } - public AccessTokenDto reissueAccessTokenIfExpired(String accessTokenValue) { + public Optional reissueAccessTokenIfExpired(String accessTokenValue) { try { + // 파싱에 성공하면 아직 유효 ⇒ Optional.empty() jwtUtil.parseAccessToken(accessTokenValue); - return null; + log.info("Access token is still valid, no reissue needed"); + return Optional.empty(); } catch (ExpiredJwtException e) { + // 만료된 경우에만 새 토큰 생성 Long adminId = Long.parseLong(e.getClaims().getSubject()); - - return createAccessTokenDto(adminId); + AccessTokenDto newToken = createAccessTokenDto(adminId); + log.info("Access token expired, issued new one for adminId={}", adminId); + return Optional.of(newToken); } }