From 5a352fa48b5e68f245263c06e1f55020f3225669 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 00:31:40 +0900 Subject: [PATCH 01/30] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=9C=20refresh=20token=20=EB=B0=9C=EA=B8=89=20=EB=B0=8F=20?= =?UTF-8?q?=ED=97=A4=EB=8D=94=EC=97=90=20=EC=9D=91=EB=8B=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../took/feature/auth/api/HeaderProvider.java | 23 ++++++++++ .../took/feature/auth/api/OAuthApi.java | 3 +- .../feature/auth/api/OAuthController.java | 15 ++++--- .../auth/application/OAuthService.java | 8 ++-- .../auth/application/UuidTokenProvider.java | 26 +++++++++++ .../auth/dto/response/AuthResponse.java | 14 ++++++ .../auth/dto/response/JwtResponse.java | 6 --- .../auth/dto/response/UserResponse.java | 13 ++++++ .../evenly/took/feature/user/domain/User.java | 2 + .../application/UuidTokenProviderTest.java | 45 +++++++++++++++++++ 10 files changed, 139 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/evenly/took/feature/auth/api/HeaderProvider.java create mode 100644 src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java create mode 100644 src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java delete mode 100644 src/main/java/com/evenly/took/feature/auth/dto/response/JwtResponse.java create mode 100644 src/main/java/com/evenly/took/feature/auth/dto/response/UserResponse.java create mode 100644 src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java diff --git a/src/main/java/com/evenly/took/feature/auth/api/HeaderProvider.java b/src/main/java/com/evenly/took/feature/auth/api/HeaderProvider.java new file mode 100644 index 0000000..eef8f34 --- /dev/null +++ b/src/main/java/com/evenly/took/feature/auth/api/HeaderProvider.java @@ -0,0 +1,23 @@ +package com.evenly.took.feature.auth.api; + +import org.springframework.stereotype.Component; + +import com.evenly.took.feature.auth.dto.response.AuthResponse; + +import jakarta.servlet.http.HttpServletResponse; + +@Component +public class HeaderProvider { + + private static final String HEADER_KEY_OF_AUTH = "Authorization"; + private static final String HEADER_VALUE_PREFIX_OF_AUTH = "Bearer %s %s"; + + public void setAuthHeader(HttpServletResponse response, AuthResponse authResponse) { + String value = buildAuthHeaderValue(authResponse.accessToken(), authResponse.refreshToken()); + response.setHeader(HEADER_KEY_OF_AUTH, value); + } + + private String buildAuthHeaderValue(String accessToken, String refreshToken) { + return String.format(HEADER_VALUE_PREFIX_OF_AUTH, accessToken, refreshToken); + } +} diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java index 2d454a4..f801700 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java @@ -42,5 +42,6 @@ SuccessResponse login( @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @PathVariable OAuthType oauthType, @Parameter(description = "소셜 서버로부터 전달받은 인가 코드", required = true) - @RequestParam String code); + @RequestParam String code, + HttpServletResponse response); } diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java index 8e4f177..28121d7 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java @@ -9,7 +9,7 @@ import com.evenly.took.feature.auth.application.OAuthService; import com.evenly.took.feature.auth.domain.OAuthType; -import com.evenly.took.feature.auth.dto.response.JwtResponse; +import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.global.response.SuccessResponse; import jakarta.servlet.http.HttpServletResponse; @@ -20,17 +20,20 @@ public class OAuthController implements OAuthApi { private final OAuthService oauthService; + private final HeaderProvider headerProvider; @GetMapping("/api/oauth/{oauthType}") - public void redirectAuthRequestUrl(@PathVariable OAuthType oauthType, HttpServletResponse response) throws - IOException { + public void redirectAuthRequestUrl( + @PathVariable OAuthType oauthType, HttpServletResponse response) throws IOException { String url = oauthService.getAuthCodeRequestUrl(oauthType); response.sendRedirect(url); } @GetMapping("/api/oauth/login/{oauthType}") - public SuccessResponse login(@PathVariable OAuthType oauthType, @RequestParam String code) { - JwtResponse jwtResponse = oauthService.loginAndGenerateToken(oauthType, code); - return SuccessResponse.of(jwtResponse.accessToken()); + public SuccessResponse login( + @PathVariable OAuthType oauthType, @RequestParam String code, HttpServletResponse response) { + AuthResponse authResponse = oauthService.loginAndGenerateToken(oauthType, code); + headerProvider.setAuthHeader(response, authResponse); + return SuccessResponse.of(authResponse.user()); } } diff --git a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java index 5ecf4cf..b628887 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java +++ b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java @@ -3,7 +3,7 @@ import org.springframework.stereotype.Service; import com.evenly.took.feature.auth.domain.OAuthType; -import com.evenly.took.feature.auth.dto.response.JwtResponse; +import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.feature.user.dao.UserRepository; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; @@ -20,18 +20,20 @@ public class OAuthService { private final UserClientComposite userClientComposite; private final UserRepository userRepository; private final JwtTokenProvider jwtTokenProvider; + private final UuidTokenProvider uuidTokenProvider; public String getAuthCodeRequestUrl(OAuthType oauthType) { return authCodeComposite.provide(oauthType); } - public JwtResponse loginAndGenerateToken(OAuthType oauthType, String authCode) { + public AuthResponse loginAndGenerateToken(OAuthType oauthType, String authCode) { User user = userClientComposite.fetch(oauthType, authCode); User savedUser = userRepository.findByOauthIdentifier(user.getOauthIdentifier()) .orElseGet(() -> userRepository.save(user)); String accessToken = jwtTokenProvider.generateAccessToken(savedUser); + String refreshToken = uuidTokenProvider.generateRefreshToken(savedUser); - return new JwtResponse(accessToken); + return new AuthResponse(accessToken, refreshToken, user); } } diff --git a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java new file mode 100644 index 0000000..29a15e0 --- /dev/null +++ b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java @@ -0,0 +1,26 @@ +package com.evenly.took.feature.auth.application; + +import java.time.Duration; +import java.util.UUID; + +import org.springframework.stereotype.Component; + +import com.evenly.took.feature.user.domain.User; +import com.evenly.took.global.redis.RedisService; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class UuidTokenProvider { + + private static final Duration EXPIRATION_OF_REFRESH_TOKEN = Duration.ofDays(7); + + private final RedisService redisService; + + public String generateRefreshToken(User user) { + String refreshToken = UUID.randomUUID().toString(); + redisService.setValueWithTTL(user.getId().toString(), refreshToken, EXPIRATION_OF_REFRESH_TOKEN); + return refreshToken; + } +} diff --git a/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java b/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java new file mode 100644 index 0000000..e41cc71 --- /dev/null +++ b/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java @@ -0,0 +1,14 @@ +package com.evenly.took.feature.auth.dto.response; + +import com.evenly.took.feature.user.domain.User; + +public record AuthResponse( + String accessToken, + String refreshToken, + UserResponse user +) { + + public AuthResponse(String accessToken, String refreshToken, User user) { + this(accessToken, refreshToken, new UserResponse(user)); + } +} diff --git a/src/main/java/com/evenly/took/feature/auth/dto/response/JwtResponse.java b/src/main/java/com/evenly/took/feature/auth/dto/response/JwtResponse.java deleted file mode 100644 index ee92c03..0000000 --- a/src/main/java/com/evenly/took/feature/auth/dto/response/JwtResponse.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.evenly.took.feature.auth.dto.response; - -public record JwtResponse( - String accessToken -) { -} diff --git a/src/main/java/com/evenly/took/feature/auth/dto/response/UserResponse.java b/src/main/java/com/evenly/took/feature/auth/dto/response/UserResponse.java new file mode 100644 index 0000000..070b02a --- /dev/null +++ b/src/main/java/com/evenly/took/feature/auth/dto/response/UserResponse.java @@ -0,0 +1,13 @@ +package com.evenly.took.feature.auth.dto.response; + +import com.evenly.took.feature.user.domain.User; + +public record UserResponse( + Long id, + String name +) { + + public UserResponse(User user) { + this(user.getId(), user.getName()); + } +} diff --git a/src/main/java/com/evenly/took/feature/user/domain/User.java b/src/main/java/com/evenly/took/feature/user/domain/User.java index bad5c7e..3955070 100644 --- a/src/main/java/com/evenly/took/feature/user/domain/User.java +++ b/src/main/java/com/evenly/took/feature/user/domain/User.java @@ -13,6 +13,7 @@ import jakarta.persistence.UniqueConstraint; import jakarta.validation.constraints.NotNull; import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -25,6 +26,7 @@ ) }) @NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor @Getter public class User extends BaseTimeEntity { diff --git a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java new file mode 100644 index 0000000..be18feb --- /dev/null +++ b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java @@ -0,0 +1,45 @@ +package com.evenly.took.feature.auth.application; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; + +import com.evenly.took.feature.auth.domain.OAuthIdentifier; +import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.user.domain.User; +import com.evenly.took.global.config.testcontainers.RedisTestConfig; +import com.evenly.took.global.redis.RedisService; +import com.evenly.took.global.service.MockTest; + +@SpringBootTest +@ActiveProfiles("test") +@Import(RedisTestConfig.class) +class UuidTokenProviderTest extends MockTest { // TODO Import 상위로 추출 + + @Autowired + UuidTokenProvider uuidTokenProvider; + + @Autowired + RedisService redisService; + + @Test + void refreshToken을_생성한다() { + // given + OAuthIdentifier oAuthIdentifier = OAuthIdentifier.builder() + .oauthId("oauth-id") + .oauthType(OAuthType.KAKAO) + .build(); + User user = new User(1L, oAuthIdentifier, "took"); + + // when + String refreshToken = uuidTokenProvider.generateRefreshToken(user); + + // then + assertThat(refreshToken).isNotNull(); + assertThat(redisService.getValue(user.getId().toString())).isEqualTo(refreshToken); + } +} From 4da0d05b1c974b407210fd54ee519e50931c0465 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 02:55:21 +0900 Subject: [PATCH 02/30] =?UTF-8?q?feat:=20=EB=A7=A4=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=EC=97=90=EC=84=9C=20token=20=EA=B2=80=EC=A6=9D=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9E=AC=EB=B0=9C=EA=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../took/feature/auth/api/HeaderHandler.java | 46 +++++++++++++++ .../took/feature/auth/api/HeaderProvider.java | 23 -------- .../feature/auth/api/OAuthController.java | 4 +- .../auth/application/OAuthService.java | 4 +- .../auth/application/UuidTokenProvider.java | 16 +++++- .../auth/dto/response/AuthResponse.java | 5 +- .../auth/dto/response/TokenResponse.java | 7 +++ .../{JwtErrorCode.java => AuthErrorCode.java} | 4 +- .../oauth/InvalidAccessTokenException.java | 14 +++++ .../oauth/InvalidRefreshTokenException.java | 14 +++++ ...eption.java => InvalidTokenException.java} | 4 +- .../took/global/redis/RedisService.java | 8 +++ .../took/global/redis/RedisServiceImpl.java | 6 ++ .../security/jwt/JwtAuthenticationFilter.java | 57 ++++++++++++------- .../global/security/jwt/JwtTokenProvider.java | 18 +++--- .../application/UuidTokenProviderTest.java | 13 +---- .../auth/jwt/JwtTokenProviderTest.java | 4 +- 17 files changed, 167 insertions(+), 80 deletions(-) create mode 100644 src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java delete mode 100644 src/main/java/com/evenly/took/feature/auth/api/HeaderProvider.java create mode 100644 src/main/java/com/evenly/took/feature/auth/dto/response/TokenResponse.java rename src/main/java/com/evenly/took/global/exception/auth/jwt/{JwtErrorCode.java => AuthErrorCode.java} (62%) create mode 100644 src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidAccessTokenException.java create mode 100644 src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidRefreshTokenException.java rename src/main/java/com/evenly/took/global/exception/auth/oauth/{InvalidJwtTokenException.java => InvalidTokenException.java} (63%) diff --git a/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java b/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java new file mode 100644 index 0000000..6bb7118 --- /dev/null +++ b/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java @@ -0,0 +1,46 @@ +package com.evenly.took.feature.auth.api; + +import org.springframework.stereotype.Component; + +import com.evenly.took.feature.auth.dto.response.TokenResponse; +import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; +import com.evenly.took.global.exception.auth.oauth.InvalidTokenException; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +@Component +public class HeaderHandler { + + private static final String HEADER_KEY_OF_AUTH = "Authorization"; + private static final String HEADER_VALUE_FORMAT_OF_AUTH = "Bearer %s %s"; + private static final String HEADER_VALUE_PREFIX_OF_AUTH = "Bearer "; + private static final String HEADER_VALUE_DELIMITER_OF_AUTH = " "; + + public void setAuthHeader(HttpServletResponse response, TokenResponse tokenResponse) { + String value = buildAuthHeaderValue(tokenResponse.accessToken(), tokenResponse.refreshToken()); + response.setHeader(HEADER_KEY_OF_AUTH, value); + } + + private String buildAuthHeaderValue(String accessToken, String refreshToken) { + return String.format(HEADER_VALUE_FORMAT_OF_AUTH, accessToken, refreshToken); + } + + public String resolveAccessToken(HttpServletRequest request) { + String bearerToken = request.getHeader(HEADER_KEY_OF_AUTH); + validateAuthHeader(bearerToken); + return bearerToken.split(HEADER_VALUE_DELIMITER_OF_AUTH)[1]; + } + + public String resolveRefreshToken(HttpServletRequest request) { + String bearerToken = request.getHeader(HEADER_KEY_OF_AUTH); + validateAuthHeader(bearerToken); + return bearerToken.split(HEADER_VALUE_DELIMITER_OF_AUTH)[2]; + } + + private void validateAuthHeader(String bearerToken) { + if (bearerToken == null || !bearerToken.startsWith(HEADER_VALUE_PREFIX_OF_AUTH)) { + throw new InvalidTokenException(AuthErrorCode.JWT_UNAUTHORIZED); + } + } +} diff --git a/src/main/java/com/evenly/took/feature/auth/api/HeaderProvider.java b/src/main/java/com/evenly/took/feature/auth/api/HeaderProvider.java deleted file mode 100644 index eef8f34..0000000 --- a/src/main/java/com/evenly/took/feature/auth/api/HeaderProvider.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.evenly.took.feature.auth.api; - -import org.springframework.stereotype.Component; - -import com.evenly.took.feature.auth.dto.response.AuthResponse; - -import jakarta.servlet.http.HttpServletResponse; - -@Component -public class HeaderProvider { - - private static final String HEADER_KEY_OF_AUTH = "Authorization"; - private static final String HEADER_VALUE_PREFIX_OF_AUTH = "Bearer %s %s"; - - public void setAuthHeader(HttpServletResponse response, AuthResponse authResponse) { - String value = buildAuthHeaderValue(authResponse.accessToken(), authResponse.refreshToken()); - response.setHeader(HEADER_KEY_OF_AUTH, value); - } - - private String buildAuthHeaderValue(String accessToken, String refreshToken) { - return String.format(HEADER_VALUE_PREFIX_OF_AUTH, accessToken, refreshToken); - } -} diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java index 28121d7..5563036 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java @@ -20,7 +20,7 @@ public class OAuthController implements OAuthApi { private final OAuthService oauthService; - private final HeaderProvider headerProvider; + private final HeaderHandler headerHandler; @GetMapping("/api/oauth/{oauthType}") public void redirectAuthRequestUrl( @@ -33,7 +33,7 @@ public void redirectAuthRequestUrl( public SuccessResponse login( @PathVariable OAuthType oauthType, @RequestParam String code, HttpServletResponse response) { AuthResponse authResponse = oauthService.loginAndGenerateToken(oauthType, code); - headerProvider.setAuthHeader(response, authResponse); + headerHandler.setAuthHeader(response, authResponse.token()); return SuccessResponse.of(authResponse.user()); } } diff --git a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java index b628887..220694d 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java +++ b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java @@ -31,8 +31,8 @@ public AuthResponse loginAndGenerateToken(OAuthType oauthType, String authCode) User savedUser = userRepository.findByOauthIdentifier(user.getOauthIdentifier()) .orElseGet(() -> userRepository.save(user)); - String accessToken = jwtTokenProvider.generateAccessToken(savedUser); - String refreshToken = uuidTokenProvider.generateRefreshToken(savedUser); + String accessToken = jwtTokenProvider.generateAccessToken(savedUser.getId().toString()); + String refreshToken = uuidTokenProvider.generateRefreshToken(savedUser.getId().toString()); return new AuthResponse(accessToken, refreshToken, user); } diff --git a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java index 29a15e0..dc8a258 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java +++ b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java @@ -5,7 +5,8 @@ import org.springframework.stereotype.Component; -import com.evenly.took.feature.user.domain.User; +import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; +import com.evenly.took.global.exception.auth.oauth.InvalidRefreshTokenException; import com.evenly.took.global.redis.RedisService; import lombok.RequiredArgsConstructor; @@ -18,9 +19,18 @@ public class UuidTokenProvider { private final RedisService redisService; - public String generateRefreshToken(User user) { + public String generateRefreshToken(String userId) { String refreshToken = UUID.randomUUID().toString(); - redisService.setValueWithTTL(user.getId().toString(), refreshToken, EXPIRATION_OF_REFRESH_TOKEN); + redisService.setValueWithTTL(userId, refreshToken, EXPIRATION_OF_REFRESH_TOKEN); return refreshToken; } + + public void validateToken(String userId, String token) { + if (!redisService.existsKey(userId)) { + throw new InvalidRefreshTokenException(AuthErrorCode.EXPIRED_REFRESH_TOKEN); + } + if (!redisService.getValue(userId).toString().equals(token)) { + throw new InvalidRefreshTokenException(AuthErrorCode.INVALID_REFRESH_TOKEN); + } + } } diff --git a/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java b/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java index e41cc71..4230888 100644 --- a/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java +++ b/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java @@ -3,12 +3,11 @@ import com.evenly.took.feature.user.domain.User; public record AuthResponse( - String accessToken, - String refreshToken, + TokenResponse token, UserResponse user ) { public AuthResponse(String accessToken, String refreshToken, User user) { - this(accessToken, refreshToken, new UserResponse(user)); + this(new TokenResponse(accessToken, refreshToken), new UserResponse(user)); } } diff --git a/src/main/java/com/evenly/took/feature/auth/dto/response/TokenResponse.java b/src/main/java/com/evenly/took/feature/auth/dto/response/TokenResponse.java new file mode 100644 index 0000000..3064002 --- /dev/null +++ b/src/main/java/com/evenly/took/feature/auth/dto/response/TokenResponse.java @@ -0,0 +1,7 @@ +package com.evenly.took.feature.auth.dto.response; + +public record TokenResponse( + String accessToken, + String refreshToken +) { +} diff --git a/src/main/java/com/evenly/took/global/exception/auth/jwt/JwtErrorCode.java b/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java similarity index 62% rename from src/main/java/com/evenly/took/global/exception/auth/jwt/JwtErrorCode.java rename to src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java index 6332163..829ab5a 100644 --- a/src/main/java/com/evenly/took/global/exception/auth/jwt/JwtErrorCode.java +++ b/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java @@ -9,9 +9,11 @@ @Getter @RequiredArgsConstructor -public enum JwtErrorCode implements ErrorCode { +public enum AuthErrorCode implements ErrorCode { JWT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "JWT를 찾을 수 없습니다."), + EXPIRED_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "refresh token이 만료되었습니다."), + INVALID_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "refresh token이 유효하지 않습니다."), ; private final HttpStatus status; diff --git a/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidAccessTokenException.java b/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidAccessTokenException.java new file mode 100644 index 0000000..64b225e --- /dev/null +++ b/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidAccessTokenException.java @@ -0,0 +1,14 @@ +package com.evenly.took.global.exception.auth.oauth; + +import com.evenly.took.global.exception.ErrorCode; +import com.evenly.took.global.exception.TookException; + +import lombok.Getter; + +@Getter +public class InvalidAccessTokenException extends TookException { + + public InvalidAccessTokenException(final ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidRefreshTokenException.java b/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidRefreshTokenException.java new file mode 100644 index 0000000..d72191e --- /dev/null +++ b/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidRefreshTokenException.java @@ -0,0 +1,14 @@ +package com.evenly.took.global.exception.auth.oauth; + +import com.evenly.took.global.exception.ErrorCode; +import com.evenly.took.global.exception.TookException; + +import lombok.Getter; + +@Getter +public class InvalidRefreshTokenException extends TookException { + + public InvalidRefreshTokenException(final ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidJwtTokenException.java b/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidTokenException.java similarity index 63% rename from src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidJwtTokenException.java rename to src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidTokenException.java index 21d3494..fa6cb73 100644 --- a/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidJwtTokenException.java +++ b/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidTokenException.java @@ -6,9 +6,9 @@ import lombok.Getter; @Getter -public class InvalidJwtTokenException extends TookException { +public class InvalidTokenException extends TookException { - public InvalidJwtTokenException(final ErrorCode errorCode) { + public InvalidTokenException(final ErrorCode errorCode) { super(errorCode); } } diff --git a/src/main/java/com/evenly/took/global/redis/RedisService.java b/src/main/java/com/evenly/took/global/redis/RedisService.java index 1c52d8f..44571e0 100644 --- a/src/main/java/com/evenly/took/global/redis/RedisService.java +++ b/src/main/java/com/evenly/took/global/redis/RedisService.java @@ -38,4 +38,12 @@ public interface RedisService { * @return 삭제 성공 여부 */ boolean deleteKey(String key); + + /** + * Redis에서 key 존재 여부를 검증합니다. + * + * @param key 검증할 키 + * @return 존재 여부 + */ + boolean existsKey(String key); } diff --git a/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java b/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java index 9545dfb..28c67a7 100644 --- a/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java +++ b/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java @@ -46,6 +46,12 @@ public boolean deleteKey(String key) { }); } + public boolean existsKey(String key) { + return executeOperation(() -> { + redisTemplate.hasKey(key); + }); + } + private boolean executeOperation(Runnable operation) { try { operation.run(); diff --git a/src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java b/src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java index 512e6c7..68606b1 100644 --- a/src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java @@ -1,12 +1,15 @@ package com.evenly.took.global.security.jwt; -import static com.evenly.took.global.exception.auth.jwt.JwtErrorCode.*; - import java.io.IOException; import org.springframework.web.filter.OncePerRequestFilter; -import com.evenly.took.global.exception.TookException; +import com.evenly.took.feature.auth.api.HeaderHandler; +import com.evenly.took.feature.auth.application.UuidTokenProvider; +import com.evenly.took.feature.auth.dto.response.TokenResponse; +import com.evenly.took.global.exception.auth.oauth.InvalidAccessTokenException; +import com.evenly.took.global.exception.auth.oauth.InvalidRefreshTokenException; +import com.evenly.took.global.exception.auth.oauth.InvalidTokenException; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; @@ -17,33 +20,43 @@ @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { - public static final String BEARER = "Bearer "; - public static final String AUTHORIZATION = "Authorization"; - private final JwtTokenProvider jwtTokenProvider; + private final UuidTokenProvider uuidTokenProvider; + private final HeaderHandler headerHandler; @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, - FilterChain filterChain) - throws ServletException, IOException { + protected void doFilterInternal( + HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { try { - String token = resolveToken(request); - - jwtTokenProvider.validateToken(token); - } catch (TookException e) { - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()); - return; + checkTokens(request, response); + filterChain.doFilter(request, response); + } catch (InvalidTokenException | InvalidRefreshTokenException ex) { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage()); // TODO 형식 통일 } - - filterChain.doFilter(request, response); } - private String resolveToken(HttpServletRequest request) { - String bearerToken = request.getHeader(AUTHORIZATION); - if (bearerToken == null || !bearerToken.startsWith(BEARER)) { - throw new TookException(JWT_UNAUTHORIZED); + private void checkTokens(HttpServletRequest request, HttpServletResponse response) + throws InvalidTokenException, InvalidRefreshTokenException { + + String accessToken = headerHandler.resolveAccessToken(request); + String refreshToken = headerHandler.resolveRefreshToken(request); + + try { + jwtTokenProvider.validateToken(accessToken); + } catch (InvalidAccessTokenException ex) { + String userId = jwtTokenProvider.getUserId(accessToken); + checkRefreshToken(userId, refreshToken, response); } - return bearerToken.substring(BEARER.length()); + } + + private void checkRefreshToken(String userId, String refreshToken, HttpServletResponse response) + throws InvalidRefreshTokenException { + + uuidTokenProvider.validateToken(userId, refreshToken); + String accessToken = jwtTokenProvider.generateAccessToken(userId); + headerHandler.setAuthHeader(response, new TokenResponse(accessToken, refreshToken)); } } diff --git a/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java b/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java index ab57653..98d4a65 100644 --- a/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java +++ b/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java @@ -1,6 +1,6 @@ package com.evenly.took.global.security.jwt; -import static com.evenly.took.global.exception.auth.jwt.JwtErrorCode.*; +import static com.evenly.took.global.exception.auth.jwt.AuthErrorCode.*; import java.nio.charset.StandardCharsets; import java.security.Key; @@ -8,9 +8,8 @@ import org.springframework.stereotype.Component; -import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.config.properties.jwt.JwtProperties; -import com.evenly.took.global.exception.auth.oauth.InvalidJwtTokenException; +import com.evenly.took.global.exception.auth.oauth.InvalidAccessTokenException; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; @@ -28,17 +27,16 @@ public class JwtTokenProvider { private final JwtProperties jwtProperties; - public String generateAccessToken(User user) { - Claims claims = generateClaims(user); + public String generateAccessToken(String userId) { + Claims claims = generateClaims(userId); Date now = new Date(); Date expiredAt = new Date(now.getTime() + jwtProperties.accessTokenExpirationMilliTime()); return buildAccessToken(claims, now, expiredAt); } - private Claims generateClaims(final User user) { - Claims claims = Jwts.claims().setSubject(user.getId().toString()); - claims.put("name", user.getName()); - return claims; + private Claims generateClaims(String userId) { + return Jwts.claims() + .setSubject(userId); } private String buildAccessToken(Claims claims, Date now, Date expiredAt) { @@ -56,7 +54,7 @@ public void validateToken(String token) { parseClaims(token); } catch (JwtException | IllegalArgumentException e) { log.error(JWT_UNAUTHORIZED.getMessage(), e); - throw new InvalidJwtTokenException(JWT_UNAUTHORIZED); + throw new InvalidAccessTokenException(JWT_UNAUTHORIZED); } } diff --git a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java index be18feb..e215756 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java @@ -8,9 +8,6 @@ import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; -import com.evenly.took.feature.auth.domain.OAuthIdentifier; -import com.evenly.took.feature.auth.domain.OAuthType; -import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.config.testcontainers.RedisTestConfig; import com.evenly.took.global.redis.RedisService; import com.evenly.took.global.service.MockTest; @@ -29,17 +26,13 @@ class UuidTokenProviderTest extends MockTest { // TODO Import 상위로 추출 @Test void refreshToken을_생성한다() { // given - OAuthIdentifier oAuthIdentifier = OAuthIdentifier.builder() - .oauthId("oauth-id") - .oauthType(OAuthType.KAKAO) - .build(); - User user = new User(1L, oAuthIdentifier, "took"); + String userId = "1"; // when - String refreshToken = uuidTokenProvider.generateRefreshToken(user); + String refreshToken = uuidTokenProvider.generateRefreshToken(userId); // then assertThat(refreshToken).isNotNull(); - assertThat(redisService.getValue(user.getId().toString())).isEqualTo(refreshToken); + assertThat(redisService.getValue(userId)).isEqualTo(refreshToken); } } diff --git a/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java index 4a50405..7b2b33a 100644 --- a/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java @@ -31,7 +31,7 @@ void setUp() { @Test void accessToken_생성_성공() { // given, when - String token = jwtTokenProvider.generateAccessToken(testUser); + String token = jwtTokenProvider.generateAccessToken(testUser.getId().toString()); // then assertThat(token).isNotNull(); @@ -40,7 +40,7 @@ void setUp() { @Test void accessToken_validate_성공() { // given - String token = jwtTokenProvider.generateAccessToken(testUser); + String token = jwtTokenProvider.generateAccessToken(testUser.getId().toString()); // when String userId = jwtTokenProvider.getUserId(token); From a3867ac7a82026c358fcc4a2ca8b0599f9a37751 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 03:23:45 +0900 Subject: [PATCH 03/30] =?UTF-8?q?test:=20OAuthService=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/OAuthServiceTest.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java diff --git a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java b/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java new file mode 100644 index 0000000..81bef5e --- /dev/null +++ b/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java @@ -0,0 +1,79 @@ +package com.evenly.took.feature.auth.application; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; + +import com.evenly.took.feature.auth.domain.OAuthIdentifier; +import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.auth.dto.response.AuthResponse; +import com.evenly.took.feature.user.dao.UserRepository; +import com.evenly.took.feature.user.domain.User; +import com.evenly.took.global.config.testcontainers.RedisTestConfig; +import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; +import com.evenly.took.global.security.client.UserClientComposite; +import com.evenly.took.global.security.jwt.JwtTokenProvider; + +@SpringBootTest +@ActiveProfiles("test") +@Import(RedisTestConfig.class) +class OAuthServiceTest { // TODO 상위 클래스 추출 + + OAuthService oauthService; + + @Mock + UserClientComposite userClientComposite; + + @Mock + AuthCodeRequestUrlProviderComposite authCodeComposite; + + @Autowired + UserRepository userRepository; + + @Autowired + JwtTokenProvider jwtTokenProvider; + + @Autowired + UuidTokenProvider uuidTokenProvider; + + @BeforeEach + void setUp() { + oauthService = new OAuthService( + authCodeComposite, + userClientComposite, + userRepository, + jwtTokenProvider, + uuidTokenProvider); + } + + @Test + void name() { + // given + OAuthIdentifier oauthIdentifier = OAuthIdentifier.builder() + .oauthId("oauth-id") + .oauthType(OAuthType.KAKAO) + .build(); + User user = User.builder() + .oauthIdentifier(oauthIdentifier) + .name("took") + .build(); + given(userClientComposite.fetch(any(OAuthType.class), anyString())) + .willReturn(user); + + // when + AuthResponse response = oauthService.loginAndGenerateToken(OAuthType.KAKAO, "code"); + + // then + assertThat(response.token().accessToken()).containsAnyOf("."); + assertThat(response.token().refreshToken()).isNotBlank(); + assertThat(response.user().name()).isEqualTo("took"); + } +} From 7892636819fc73ec169bfb71b26ebd018a9a3780 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 03:31:53 +0900 Subject: [PATCH 04/30] =?UTF-8?q?refac:=20refresh=20token=20=EB=A7=8C?= =?UTF-8?q?=EB=A3=8C=20=ED=99=98=EA=B2=BD=20=EB=B3=80=EC=88=98=20=EC=B6=94?= =?UTF-8?q?=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../took/feature/auth/application/UuidTokenProvider.java | 7 ++++--- .../took/global/config/properties/PropertiesConfig.java | 4 ++-- .../jwt/{JwtProperties.java => AuthProperties.java} | 7 ++++--- .../evenly/took/global/security/jwt/JwtTokenProvider.java | 8 ++++---- src/main/resources/application-local.yml | 3 ++- .../took/feature/auth/jwt/JwtTokenProviderTest.java | 6 +++--- 6 files changed, 19 insertions(+), 16 deletions(-) rename src/main/java/com/evenly/took/global/config/properties/jwt/{JwtProperties.java => AuthProperties.java} (65%) diff --git a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java index dc8a258..069c85f 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java +++ b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java @@ -5,6 +5,7 @@ import org.springframework.stereotype.Component; +import com.evenly.took.global.config.properties.jwt.AuthProperties; import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; import com.evenly.took.global.exception.auth.oauth.InvalidRefreshTokenException; import com.evenly.took.global.redis.RedisService; @@ -15,13 +16,13 @@ @RequiredArgsConstructor public class UuidTokenProvider { - private static final Duration EXPIRATION_OF_REFRESH_TOKEN = Duration.ofDays(7); - + private final AuthProperties authProperties; private final RedisService redisService; public String generateRefreshToken(String userId) { String refreshToken = UUID.randomUUID().toString(); - redisService.setValueWithTTL(userId, refreshToken, EXPIRATION_OF_REFRESH_TOKEN); + Duration expiration = Duration.ofDays(authProperties.refreshTokenExpirationDay()); + redisService.setValueWithTTL(userId, refreshToken, expiration); return refreshToken; } diff --git a/src/main/java/com/evenly/took/global/config/properties/PropertiesConfig.java b/src/main/java/com/evenly/took/global/config/properties/PropertiesConfig.java index cbba76a..c02d242 100644 --- a/src/main/java/com/evenly/took/global/config/properties/PropertiesConfig.java +++ b/src/main/java/com/evenly/took/global/config/properties/PropertiesConfig.java @@ -3,10 +3,10 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; -import com.evenly.took.global.config.properties.jwt.JwtProperties; +import com.evenly.took.global.config.properties.jwt.AuthProperties; @EnableConfigurationProperties({ - JwtProperties.class, + AuthProperties.class, }) @Configuration public class PropertiesConfig { diff --git a/src/main/java/com/evenly/took/global/config/properties/jwt/JwtProperties.java b/src/main/java/com/evenly/took/global/config/properties/jwt/AuthProperties.java similarity index 65% rename from src/main/java/com/evenly/took/global/config/properties/jwt/JwtProperties.java rename to src/main/java/com/evenly/took/global/config/properties/jwt/AuthProperties.java index de63719..b7e26ba 100644 --- a/src/main/java/com/evenly/took/global/config/properties/jwt/JwtProperties.java +++ b/src/main/java/com/evenly/took/global/config/properties/jwt/AuthProperties.java @@ -2,10 +2,11 @@ import org.springframework.boot.context.properties.ConfigurationProperties; -@ConfigurationProperties(prefix = "jwt") -public record JwtProperties( +@ConfigurationProperties(prefix = "auth") +public record AuthProperties( String accessTokenSecret, - Long accessTokenExpirationTime + Long accessTokenExpirationTime, + Long refreshTokenExpirationDay ) { public Long accessTokenExpirationMilliTime() { diff --git a/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java b/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java index 98d4a65..7a46dbc 100644 --- a/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java +++ b/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java @@ -8,7 +8,7 @@ import org.springframework.stereotype.Component; -import com.evenly.took.global.config.properties.jwt.JwtProperties; +import com.evenly.took.global.config.properties.jwt.AuthProperties; import com.evenly.took.global.exception.auth.oauth.InvalidAccessTokenException; import io.jsonwebtoken.Claims; @@ -25,12 +25,12 @@ @RequiredArgsConstructor public class JwtTokenProvider { - private final JwtProperties jwtProperties; + private final AuthProperties authProperties; public String generateAccessToken(String userId) { Claims claims = generateClaims(userId); Date now = new Date(); - Date expiredAt = new Date(now.getTime() + jwtProperties.accessTokenExpirationMilliTime()); + Date expiredAt = new Date(now.getTime() + authProperties.accessTokenExpirationMilliTime()); return buildAccessToken(claims, now, expiredAt); } @@ -73,7 +73,7 @@ private Jws parseClaims(String token) { } private Key getSigningKey() { - String secret = jwtProperties.accessTokenSecret(); + String secret = authProperties.accessTokenSecret(); return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)); } } diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 66e9e99..152b54f 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -54,6 +54,7 @@ ssh: db-host: ${DB_HOST} db-port: ${DB_PORT} -jwt: +auth: access-token-secret: ${JWT_ACCESS_TOKEN_SECRET:secret} access-token-expiration-time: ${JWT_ACCESS_TOKEN_EXPIRATION_TIME:7200} + refresh-token-expiration-day: ${REFRESH_TOKEN_EXPIRATION_DAY} diff --git a/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java index 7b2b33a..3d3c3f9 100644 --- a/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java @@ -7,7 +7,7 @@ import org.junit.jupiter.api.Test; import com.evenly.took.feature.user.domain.User; -import com.evenly.took.global.config.properties.jwt.JwtProperties; +import com.evenly.took.global.config.properties.jwt.AuthProperties; import com.evenly.took.global.exception.TookException; import com.evenly.took.global.security.jwt.JwtTokenProvider; import com.evenly.took.global.service.MockTest; @@ -24,8 +24,8 @@ void setUp() { String accessTokenSecret = "secretKey123secretKey123secretKey123"; - JwtProperties jwtProperties = new JwtProperties(accessTokenSecret, 3600L); - jwtTokenProvider = new JwtTokenProvider(jwtProperties); + AuthProperties authProperties = new AuthProperties(accessTokenSecret, 3600L, 1L); + jwtTokenProvider = new JwtTokenProvider(authProperties); } @Test From 083084097b329d1dbe2d8417a6db63648a74ad08 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 03:58:00 +0900 Subject: [PATCH 05/30] =?UTF-8?q?test:=20UuidTokenProvider=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/UuidTokenProvider.java | 7 ++-- .../config/properties/jwt/AuthProperties.java | 2 +- .../took/global/redis/RedisService.java | 8 ---- .../took/global/redis/RedisServiceImpl.java | 6 --- src/main/resources/application-local.yml | 2 +- .../application/UuidTokenProviderTest.java | 38 ++++++++++++++++++- src/test/resources/application-test.yml | 5 +++ 7 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java index 069c85f..0f01ed1 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java +++ b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java @@ -21,16 +21,17 @@ public class UuidTokenProvider { public String generateRefreshToken(String userId) { String refreshToken = UUID.randomUUID().toString(); - Duration expiration = Duration.ofDays(authProperties.refreshTokenExpirationDay()); + Duration expiration = Duration.ofSeconds(authProperties.refreshTokenExpirationTime()); redisService.setValueWithTTL(userId, refreshToken, expiration); return refreshToken; } public void validateToken(String userId, String token) { - if (!redisService.existsKey(userId)) { + Object savedToken = redisService.getValue(userId); + if (savedToken == null) { throw new InvalidRefreshTokenException(AuthErrorCode.EXPIRED_REFRESH_TOKEN); } - if (!redisService.getValue(userId).toString().equals(token)) { + if (!savedToken.toString().equals(token)) { throw new InvalidRefreshTokenException(AuthErrorCode.INVALID_REFRESH_TOKEN); } } diff --git a/src/main/java/com/evenly/took/global/config/properties/jwt/AuthProperties.java b/src/main/java/com/evenly/took/global/config/properties/jwt/AuthProperties.java index b7e26ba..24ee39c 100644 --- a/src/main/java/com/evenly/took/global/config/properties/jwt/AuthProperties.java +++ b/src/main/java/com/evenly/took/global/config/properties/jwt/AuthProperties.java @@ -6,7 +6,7 @@ public record AuthProperties( String accessTokenSecret, Long accessTokenExpirationTime, - Long refreshTokenExpirationDay + Long refreshTokenExpirationTime ) { public Long accessTokenExpirationMilliTime() { diff --git a/src/main/java/com/evenly/took/global/redis/RedisService.java b/src/main/java/com/evenly/took/global/redis/RedisService.java index 44571e0..1c52d8f 100644 --- a/src/main/java/com/evenly/took/global/redis/RedisService.java +++ b/src/main/java/com/evenly/took/global/redis/RedisService.java @@ -38,12 +38,4 @@ public interface RedisService { * @return 삭제 성공 여부 */ boolean deleteKey(String key); - - /** - * Redis에서 key 존재 여부를 검증합니다. - * - * @param key 검증할 키 - * @return 존재 여부 - */ - boolean existsKey(String key); } diff --git a/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java b/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java index 28c67a7..9545dfb 100644 --- a/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java +++ b/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java @@ -46,12 +46,6 @@ public boolean deleteKey(String key) { }); } - public boolean existsKey(String key) { - return executeOperation(() -> { - redisTemplate.hasKey(key); - }); - } - private boolean executeOperation(Runnable operation) { try { operation.run(); diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 152b54f..06e150a 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -57,4 +57,4 @@ ssh: auth: access-token-secret: ${JWT_ACCESS_TOKEN_SECRET:secret} access-token-expiration-time: ${JWT_ACCESS_TOKEN_EXPIRATION_TIME:7200} - refresh-token-expiration-day: ${REFRESH_TOKEN_EXPIRATION_DAY} + refresh-token-expiration-time: ${REFRESH_TOKEN_EXPIRATION_TIME} diff --git a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java index e215756..2a909da 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java @@ -9,6 +9,7 @@ import org.springframework.test.context.ActiveProfiles; import com.evenly.took.global.config.testcontainers.RedisTestConfig; +import com.evenly.took.global.exception.auth.oauth.InvalidRefreshTokenException; import com.evenly.took.global.redis.RedisService; import com.evenly.took.global.service.MockTest; @@ -24,7 +25,7 @@ class UuidTokenProviderTest extends MockTest { // TODO Import 상위로 추출 RedisService redisService; @Test - void refreshToken을_생성한다() { + void 갱신_토큰을_생성한다() { // given String userId = "1"; @@ -35,4 +36,39 @@ class UuidTokenProviderTest extends MockTest { // TODO Import 상위로 추출 assertThat(refreshToken).isNotNull(); assertThat(redisService.getValue(userId)).isEqualTo(refreshToken); } + + @Test + void 갱신_토큰_생성_후_만료시간에_의한_만료_여부를_확인한다() throws InterruptedException { + // given + String userId = "1"; + + // when + uuidTokenProvider.generateRefreshToken(userId); + + // then + assertThat(redisService.getValue(userId)).isNotNull(); + Thread.sleep(1500); + assertThat(redisService.getValue(userId)).isNull(); + } + + @Test + void 갱신_토큰이_존재하지_않는_경우_예외를_반환한다() { + // given + String userId = "invalid"; + + // when & then + assertThatThrownBy(() -> uuidTokenProvider.validateToken(userId, "dummy")) + .isInstanceOf(InvalidRefreshTokenException.class); + } + + @Test + void 갱신_토큰이_유효하지_않은_경우_예외를_반환한다() { + // given + String userId = "1"; + String refreshToken = uuidTokenProvider.generateRefreshToken(userId); + + // when & then + assertThatThrownBy(() -> uuidTokenProvider.validateToken(userId, refreshToken + "invalid")) + .isInstanceOf(InvalidRefreshTokenException.class); + } } diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index d03a711..ef17695 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -23,3 +23,8 @@ logging: type: descriptor: sql: trace + +auth: + access-token-secret: dummy_access_token_secret_dummy_access_token_secret + access-token-expiration-time: 1 + refresh-token-expiration-time: 1 From 3b18bd7c058c060e1211bd1f6b58c97dcfe87f8b Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 07:07:40 +0900 Subject: [PATCH 06/30] =?UTF-8?q?fix:=20=EC=9D=B8=EC=A6=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=ED=86=B5=ED=95=A9=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=ED=95=98=EB=A9=B4=EC=84=9C=20=EC=9E=98=EB=AA=BB=EB=90=9C=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/UuidTokenProvider.java | 12 ++- .../config/security/WebSecurityConfig.java | 17 ++-- .../exception/auth/jwt/AuthErrorCode.java | 1 + .../took/global/redis/RedisService.java | 5 ++ .../took/global/redis/RedisServiceImpl.java | 6 ++ .../security/jwt/JwtAuthenticationFilter.java | 33 ++++--- .../global/security/jwt/JwtTokenProvider.java | 11 ++- .../auth/api/OAuthIntegrationTest.java | 85 +++++++++++++++++++ .../feature/auth/api/TestAuthController.java | 12 +++ .../application/UuidTokenProviderTest.java | 32 +++---- .../took/global/domain/TestUserFactory.java | 11 +++ .../global/integration/IntegrationTest.java | 10 +-- src/test/resources/application-test.yml | 4 +- 13 files changed, 187 insertions(+), 52 deletions(-) create mode 100644 src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java create mode 100644 src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java diff --git a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java index 0f01ed1..045ae6e 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java +++ b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java @@ -22,17 +22,15 @@ public class UuidTokenProvider { public String generateRefreshToken(String userId) { String refreshToken = UUID.randomUUID().toString(); Duration expiration = Duration.ofSeconds(authProperties.refreshTokenExpirationTime()); - redisService.setValueWithTTL(userId, refreshToken, expiration); + redisService.setValueWithTTL(refreshToken, userId, expiration); return refreshToken; } - public void validateToken(String userId, String token) { - Object savedToken = redisService.getValue(userId); - if (savedToken == null) { + public String getUserId(String token) { + Object userId = redisService.getValue(token); + if (userId == null) { throw new InvalidRefreshTokenException(AuthErrorCode.EXPIRED_REFRESH_TOKEN); } - if (!savedToken.toString().equals(token)) { - throw new InvalidRefreshTokenException(AuthErrorCode.INVALID_REFRESH_TOKEN); - } + return userId.toString(); } } diff --git a/src/main/java/com/evenly/took/global/config/security/WebSecurityConfig.java b/src/main/java/com/evenly/took/global/config/security/WebSecurityConfig.java index fd140c1..1537c0d 100644 --- a/src/main/java/com/evenly/took/global/config/security/WebSecurityConfig.java +++ b/src/main/java/com/evenly/took/global/config/security/WebSecurityConfig.java @@ -14,6 +14,8 @@ import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import jakarta.servlet.http.HttpServletResponse; + @Configuration @EnableWebSecurity public class WebSecurityConfig { @@ -34,11 +36,16 @@ public SecurityFilterChain swaggerFilterChain(HttpSecurity http) throws Exceptio public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { defaultFilterChain(http); - http.authorizeHttpRequests(authorize -> authorize - .requestMatchers("/public/**").permitAll() - .requestMatchers("/api/health").permitAll() - .requestMatchers("/api/oauth").permitAll() - .anyRequest().authenticated()); + http.exceptionHandling(exception -> exception + .authenticationEntryPoint((request, response, authException) -> { + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); + }) + ) // TODO 예외 응답 형식 통일 + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/public/**").permitAll() + .requestMatchers("/api/health").permitAll() + .requestMatchers("/api/**").permitAll() + .anyRequest().authenticated()); return http.build(); } diff --git a/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java b/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java index 829ab5a..0e93bcb 100644 --- a/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java +++ b/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java @@ -14,6 +14,7 @@ public enum AuthErrorCode implements ErrorCode { JWT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "JWT를 찾을 수 없습니다."), EXPIRED_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "refresh token이 만료되었습니다."), INVALID_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "refresh token이 유효하지 않습니다."), + INVALID_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, "access token이 유효하지 않습니다."), ; private final HttpStatus status; diff --git a/src/main/java/com/evenly/took/global/redis/RedisService.java b/src/main/java/com/evenly/took/global/redis/RedisService.java index 1c52d8f..ebd81b7 100644 --- a/src/main/java/com/evenly/took/global/redis/RedisService.java +++ b/src/main/java/com/evenly/took/global/redis/RedisService.java @@ -38,4 +38,9 @@ public interface RedisService { * @return 삭제 성공 여부 */ boolean deleteKey(String key); + + /** + * Redis에서 모든 key-value를 삭제합니다. + */ + void deleteAllKeys(); } diff --git a/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java b/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java index 9545dfb..2950511 100644 --- a/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java +++ b/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java @@ -46,6 +46,12 @@ public boolean deleteKey(String key) { }); } + public void deleteAllKeys() { + executeOperation(() -> { + redisTemplate.getConnectionFactory().getConnection().serverCommands().flushAll(); + }); + } + private boolean executeOperation(Runnable operation) { try { operation.run(); diff --git a/src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java b/src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java index 68606b1..037d07b 100644 --- a/src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java @@ -1,15 +1,16 @@ package com.evenly.took.global.security.jwt; import java.io.IOException; +import java.util.List; +import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import com.evenly.took.feature.auth.api.HeaderHandler; import com.evenly.took.feature.auth.application.UuidTokenProvider; import com.evenly.took.feature.auth.dto.response.TokenResponse; +import com.evenly.took.global.exception.TookException; import com.evenly.took.global.exception.auth.oauth.InvalidAccessTokenException; -import com.evenly.took.global.exception.auth.oauth.InvalidRefreshTokenException; -import com.evenly.took.global.exception.auth.oauth.InvalidTokenException; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; @@ -17,13 +18,25 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; +@Component @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { + private static final List EXCLUDE_PATHS = List.of( + "/public", + "/api/health", + "/api/oauth/login"); + private final JwtTokenProvider jwtTokenProvider; private final UuidTokenProvider uuidTokenProvider; private final HeaderHandler headerHandler; + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + String path = request.getRequestURI(); + return EXCLUDE_PATHS.stream().anyMatch(path::startsWith); + } + @Override protected void doFilterInternal( HttpServletRequest request, @@ -33,29 +46,23 @@ protected void doFilterInternal( try { checkTokens(request, response); filterChain.doFilter(request, response); - } catch (InvalidTokenException | InvalidRefreshTokenException ex) { + } catch (TookException ex) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage()); // TODO 형식 통일 } } - private void checkTokens(HttpServletRequest request, HttpServletResponse response) - throws InvalidTokenException, InvalidRefreshTokenException { - + private void checkTokens(HttpServletRequest request, HttpServletResponse response) { String accessToken = headerHandler.resolveAccessToken(request); String refreshToken = headerHandler.resolveRefreshToken(request); - try { jwtTokenProvider.validateToken(accessToken); } catch (InvalidAccessTokenException ex) { - String userId = jwtTokenProvider.getUserId(accessToken); - checkRefreshToken(userId, refreshToken, response); + checkRefreshToken(refreshToken, response); } } - private void checkRefreshToken(String userId, String refreshToken, HttpServletResponse response) - throws InvalidRefreshTokenException { - - uuidTokenProvider.validateToken(userId, refreshToken); + private void checkRefreshToken(String refreshToken, HttpServletResponse response) { + String userId = uuidTokenProvider.getUserId(refreshToken); String accessToken = jwtTokenProvider.generateAccessToken(userId); headerHandler.setAuthHeader(response, new TokenResponse(accessToken, refreshToken)); } diff --git a/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java b/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java index 7a46dbc..b50dfc6 100644 --- a/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java +++ b/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Component; import com.evenly.took.global.config.properties.jwt.AuthProperties; +import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; import com.evenly.took.global.exception.auth.oauth.InvalidAccessTokenException; import io.jsonwebtoken.Claims; @@ -59,9 +60,13 @@ public void validateToken(String token) { } public String getUserId(String token) { - return parseClaims(token) - .getBody() - .getSubject(); + try { + return parseClaims(token) + .getBody() + .getSubject(); + } catch (JwtException ex) { + throw new InvalidAccessTokenException(AuthErrorCode.INVALID_ACCESS_TOKEN); + } } private Jws parseClaims(String token) { diff --git a/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java b/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java new file mode 100644 index 0000000..9b810ca --- /dev/null +++ b/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java @@ -0,0 +1,85 @@ +package com.evenly.took.feature.auth.api; + +import static io.restassured.RestAssured.*; +import static org.mockito.ArgumentMatchers.*; + +import org.junit.jupiter.api.Test; +import org.mockito.BDDMockito; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.user.domain.User; +import com.evenly.took.global.domain.TestUserFactory; +import com.evenly.took.global.integration.IntegrationTest; +import com.evenly.took.global.security.client.UserClientComposite; + +public class OAuthIntegrationTest extends IntegrationTest { + + @MockitoBean + UserClientComposite userClientComposite; + + @Test + void 로그인시_사용자_정보를_반환한다() { + User user = TestUserFactory.createMockUser("took"); + BDDMockito.given(userClientComposite.fetch(any(OAuthType.class), anyString())) + .willReturn(user); + + given().log().all() + .when().get("/api/oauth/login/KAKAO?code=code") + .then().log().all() + .statusCode(200); + } + + @Test + void 유효하지_않은_액세스_토큰과_유효하지_않은_리프레쉬_토큰일_경우_401_예외를_반환한다() { + User user = TestUserFactory.createMockUser("took"); + BDDMockito.given(userClientComposite.fetch(any(OAuthType.class), anyString())) + .willReturn(user); + + given().log().all() + .header("Authorization", "Bearer invalid.access.token invalid-refresh-token") + .when().get("/api/test") + .then().log().all() + .statusCode(401); + } + + @Test + void 유효하지_않은_액세스_토큰과_유효한_리프레쉬_토큰일_경우_액세스_토큰을_갱신한다() { + User user = TestUserFactory.createMockUser("took"); + BDDMockito.given(userClientComposite.fetch(any(OAuthType.class), anyString())) + .willReturn(user); + + String tokenHeader = given().log().all() + .when().get("/api/oauth/login/KAKAO?code=code") + .then().log().all() + .statusCode(200) + .extract() + .header("Authorization"); + + given().log().all() + .header("Authorization", "Bearer %s %s".formatted("invalid", tokenHeader.split(" ")[2])) + .when().get("/api/test") + .then().log().all() + .statusCode(200); + } + + @Test + void 유효한_액세스_토큰과_유효한_리프레쉬_토큰일_경우_예외를_반환하지_않는다() { + User user = TestUserFactory.createMockUser("took"); + BDDMockito.given(userClientComposite.fetch(any(OAuthType.class), anyString())) + .willReturn(user); + + String tokenHeader = given().log().all() + .when().get("/api/oauth/login/KAKAO?code=code") + .then().log().all() + .statusCode(200) + .extract() + .header("Authorization"); + + given().log().all() + .header("Authorization", tokenHeader) + .when().get("/api/test") + .then().log().all() + .statusCode(200); + } +} diff --git a/src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java b/src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java new file mode 100644 index 0000000..676b7b3 --- /dev/null +++ b/src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java @@ -0,0 +1,12 @@ +package com.evenly.took.feature.auth.api; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestAuthController { + + @GetMapping("/api/test") + public void test() { + } +} diff --git a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java index 2a909da..5dd5c38 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java @@ -2,6 +2,7 @@ import static org.assertj.core.api.Assertions.*; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -24,8 +25,13 @@ class UuidTokenProviderTest extends MockTest { // TODO Import 상위로 추출 @Autowired RedisService redisService; + @BeforeEach + void setUp() { + redisService.deleteAllKeys(); + } + @Test - void 갱신_토큰을_생성한다() { + void 리프레쉬_토큰을_생성한다() { // given String userId = "1"; @@ -34,41 +40,37 @@ class UuidTokenProviderTest extends MockTest { // TODO Import 상위로 추출 // then assertThat(refreshToken).isNotNull(); - assertThat(redisService.getValue(userId)).isEqualTo(refreshToken); + assertThat(redisService.getValue(refreshToken)).isEqualTo(userId); } @Test - void 갱신_토큰_생성_후_만료시간에_의한_만료_여부를_확인한다() throws InterruptedException { + void 리프레쉬_토큰_생성_후_만료시간에_의한_만료_여부를_확인한다() throws InterruptedException { // given String userId = "1"; // when - uuidTokenProvider.generateRefreshToken(userId); + String refreshToken = uuidTokenProvider.generateRefreshToken(userId); // then - assertThat(redisService.getValue(userId)).isNotNull(); - Thread.sleep(1500); - assertThat(redisService.getValue(userId)).isNull(); + assertThat(redisService.getValue(refreshToken)).isNotNull(); + Thread.sleep(6000); + assertThat(redisService.getValue(refreshToken)).isNull(); } @Test - void 갱신_토큰이_존재하지_않는_경우_예외를_반환한다() { - // given - String userId = "invalid"; - - // when & then - assertThatThrownBy(() -> uuidTokenProvider.validateToken(userId, "dummy")) + void 리프레쉬_토큰이_존재하지_않는_경우_예외를_반환한다() { + assertThatThrownBy(() -> uuidTokenProvider.getUserId("dummy")) .isInstanceOf(InvalidRefreshTokenException.class); } @Test - void 갱신_토큰이_유효하지_않은_경우_예외를_반환한다() { + void 리프레쉬_토큰이_유효하지_않은_경우_예외를_반환한다() { // given String userId = "1"; String refreshToken = uuidTokenProvider.generateRefreshToken(userId); // when & then - assertThatThrownBy(() -> uuidTokenProvider.validateToken(userId, refreshToken + "invalid")) + assertThatThrownBy(() -> uuidTokenProvider.getUserId(refreshToken + "invalid")) .isInstanceOf(InvalidRefreshTokenException.class); } } diff --git a/src/test/java/com/evenly/took/global/domain/TestUserFactory.java b/src/test/java/com/evenly/took/global/domain/TestUserFactory.java index c3592ab..b598130 100644 --- a/src/test/java/com/evenly/took/global/domain/TestUserFactory.java +++ b/src/test/java/com/evenly/took/global/domain/TestUserFactory.java @@ -24,4 +24,15 @@ public static User createMockUser(String name, OAuthIdentifier oauthIdentifier) ReflectionTestUtils.setField(mcokUser, "id", 1L); return mcokUser; } + + public static User createMockUser(String name) { + OAuthIdentifier oauthIdentifier = OAuthIdentifier.builder() + .oauthId("oauth-id") + .oauthType(OAuthType.KAKAO) + .build(); + return User.builder() + .oauthIdentifier(oauthIdentifier) + .name(name) + .build(); + } } diff --git a/src/test/java/com/evenly/took/global/integration/IntegrationTest.java b/src/test/java/com/evenly/took/global/integration/IntegrationTest.java index d800653..702e76d 100644 --- a/src/test/java/com/evenly/took/global/integration/IntegrationTest.java +++ b/src/test/java/com/evenly/took/global/integration/IntegrationTest.java @@ -1,24 +1,20 @@ package com.evenly.took.global.integration; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.transaction.annotation.Transactional; +import com.evenly.took.global.config.testcontainers.RedisTestConfig; import com.fasterxml.jackson.databind.ObjectMapper; import io.restassured.RestAssured; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ExtendWith(SpringExtension.class) -@Transactional @ActiveProfiles("test") -@Disabled +@Import(RedisTestConfig.class) public abstract class IntegrationTest { @LocalServerPort diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index ef17695..2617948 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -26,5 +26,5 @@ logging: auth: access-token-secret: dummy_access_token_secret_dummy_access_token_secret - access-token-expiration-time: 1 - refresh-token-expiration-time: 1 + access-token-expiration-time: 3600 + refresh-token-expiration-time: 5 From 360d0e9e7b62f920cfa837d98052b78a4f2d8bc2 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 07:08:48 +0900 Subject: [PATCH 07/30] =?UTF-8?q?refac:=20=EC=9D=B8=EC=A6=9D=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{JwtAuthenticationFilter.java => AuthenticationFilter.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/com/evenly/took/global/security/jwt/{JwtAuthenticationFilter.java => AuthenticationFilter.java} (97%) diff --git a/src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java b/src/main/java/com/evenly/took/global/security/jwt/AuthenticationFilter.java similarity index 97% rename from src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java rename to src/main/java/com/evenly/took/global/security/jwt/AuthenticationFilter.java index 037d07b..e41efa9 100644 --- a/src/main/java/com/evenly/took/global/security/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/security/jwt/AuthenticationFilter.java @@ -20,7 +20,7 @@ @Component @RequiredArgsConstructor -public class JwtAuthenticationFilter extends OncePerRequestFilter { +public class AuthenticationFilter extends OncePerRequestFilter { private static final List EXCLUDE_PATHS = List.of( "/public", From 3bc77ac293fcb3a8c3c144693ea4f53deb1602a6 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 07:10:57 +0900 Subject: [PATCH 08/30] =?UTF-8?q?test:=20mock=20user=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/auth/application/OAuthServiceTest.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java b/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java index 81bef5e..96170b0 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java @@ -12,12 +12,12 @@ import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; -import com.evenly.took.feature.auth.domain.OAuthIdentifier; import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.feature.user.dao.UserRepository; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.config.testcontainers.RedisTestConfig; +import com.evenly.took.global.domain.TestUserFactory; import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; import com.evenly.took.global.security.client.UserClientComposite; import com.evenly.took.global.security.jwt.JwtTokenProvider; @@ -55,16 +55,9 @@ void setUp() { } @Test - void name() { + void 로그인시_토큰과_사용자_정보를_반환한다() { // given - OAuthIdentifier oauthIdentifier = OAuthIdentifier.builder() - .oauthId("oauth-id") - .oauthType(OAuthType.KAKAO) - .build(); - User user = User.builder() - .oauthIdentifier(oauthIdentifier) - .name("took") - .build(); + User user = TestUserFactory.createMockUser("took"); given(userClientComposite.fetch(any(OAuthType.class), anyString())) .willReturn(user); From 1e837de4b1091251e2faf1e966e00d6f9db43385 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 07:14:37 +0900 Subject: [PATCH 09/30] =?UTF-8?q?test:=20ServiceTest=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/auth/application/OAuthServiceTest.java | 10 ++-------- .../auth/application/UuidTokenProviderTest.java | 11 ++--------- .../com/evenly/took/global/service/ServiceTest.java | 13 +++++++++++++ 3 files changed, 17 insertions(+), 17 deletions(-) create mode 100644 src/test/java/com/evenly/took/global/service/ServiceTest.java diff --git a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java b/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java index 96170b0..b8fb77a 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java @@ -8,24 +8,18 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.ActiveProfiles; import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.feature.user.dao.UserRepository; import com.evenly.took.feature.user.domain.User; -import com.evenly.took.global.config.testcontainers.RedisTestConfig; import com.evenly.took.global.domain.TestUserFactory; import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; import com.evenly.took.global.security.client.UserClientComposite; import com.evenly.took.global.security.jwt.JwtTokenProvider; +import com.evenly.took.global.service.ServiceTest; -@SpringBootTest -@ActiveProfiles("test") -@Import(RedisTestConfig.class) -class OAuthServiceTest { // TODO 상위 클래스 추출 +class OAuthServiceTest extends ServiceTest { OAuthService oauthService; diff --git a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java index 5dd5c38..385bf74 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java @@ -5,19 +5,12 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.ActiveProfiles; -import com.evenly.took.global.config.testcontainers.RedisTestConfig; import com.evenly.took.global.exception.auth.oauth.InvalidRefreshTokenException; import com.evenly.took.global.redis.RedisService; -import com.evenly.took.global.service.MockTest; +import com.evenly.took.global.service.ServiceTest; -@SpringBootTest -@ActiveProfiles("test") -@Import(RedisTestConfig.class) -class UuidTokenProviderTest extends MockTest { // TODO Import 상위로 추출 +class UuidTokenProviderTest extends ServiceTest { @Autowired UuidTokenProvider uuidTokenProvider; diff --git a/src/test/java/com/evenly/took/global/service/ServiceTest.java b/src/test/java/com/evenly/took/global/service/ServiceTest.java new file mode 100644 index 0000000..ab417e5 --- /dev/null +++ b/src/test/java/com/evenly/took/global/service/ServiceTest.java @@ -0,0 +1,13 @@ +package com.evenly.took.global.service; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; + +import com.evenly.took.global.config.testcontainers.RedisTestConfig; + +@SpringBootTest +@ActiveProfiles("test") +@Import(RedisTestConfig.class) +public abstract class ServiceTest { +} From 9bcacd8cc6381d911f8e6c46493b1992d7740e53 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 07:17:53 +0900 Subject: [PATCH 10/30] =?UTF-8?q?refac:=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EA=B8=B0=EC=A1=B4=20=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=EB=9E=91=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/evenly/took/feature/auth/application/OAuthService.java | 3 ++- .../global/security/{jwt => auth}/AuthenticationFilter.java | 3 +-- .../took/global/security/{jwt => auth}/JwtTokenProvider.java | 2 +- .../security/auth}/UuidTokenProvider.java | 2 +- .../evenly/took/feature/auth/application/OAuthServiceTest.java | 3 ++- .../took/feature/auth/application/UuidTokenProviderTest.java | 1 + .../com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java | 2 +- 7 files changed, 9 insertions(+), 7 deletions(-) rename src/main/java/com/evenly/took/global/security/{jwt => auth}/AuthenticationFilter.java (95%) rename src/main/java/com/evenly/took/global/security/{jwt => auth}/JwtTokenProvider.java (98%) rename src/main/java/com/evenly/took/{feature/auth/application => global/security/auth}/UuidTokenProvider.java (95%) diff --git a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java index 220694d..b93a7f6 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java +++ b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java @@ -6,9 +6,10 @@ import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.feature.user.dao.UserRepository; import com.evenly.took.feature.user.domain.User; +import com.evenly.took.global.security.auth.JwtTokenProvider; +import com.evenly.took.global.security.auth.UuidTokenProvider; import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; import com.evenly.took.global.security.client.UserClientComposite; -import com.evenly.took.global.security.jwt.JwtTokenProvider; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/evenly/took/global/security/jwt/AuthenticationFilter.java b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java similarity index 95% rename from src/main/java/com/evenly/took/global/security/jwt/AuthenticationFilter.java rename to src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java index e41efa9..dff8b67 100644 --- a/src/main/java/com/evenly/took/global/security/jwt/AuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java @@ -1,4 +1,4 @@ -package com.evenly.took.global.security.jwt; +package com.evenly.took.global.security.auth; import java.io.IOException; import java.util.List; @@ -7,7 +7,6 @@ import org.springframework.web.filter.OncePerRequestFilter; import com.evenly.took.feature.auth.api.HeaderHandler; -import com.evenly.took.feature.auth.application.UuidTokenProvider; import com.evenly.took.feature.auth.dto.response.TokenResponse; import com.evenly.took.global.exception.TookException; import com.evenly.took.global.exception.auth.oauth.InvalidAccessTokenException; diff --git a/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java b/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java similarity index 98% rename from src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java rename to src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java index b50dfc6..a67ddcc 100644 --- a/src/main/java/com/evenly/took/global/security/jwt/JwtTokenProvider.java +++ b/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java @@ -1,4 +1,4 @@ -package com.evenly.took.global.security.jwt; +package com.evenly.took.global.security.auth; import static com.evenly.took.global.exception.auth.jwt.AuthErrorCode.*; diff --git a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java b/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java similarity index 95% rename from src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java rename to src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java index 045ae6e..6aa5a6c 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java +++ b/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java @@ -1,4 +1,4 @@ -package com.evenly.took.feature.auth.application; +package com.evenly.took.global.security.auth; import java.time.Duration; import java.util.UUID; diff --git a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java b/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java index b8fb77a..627ee76 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java @@ -14,9 +14,10 @@ import com.evenly.took.feature.user.dao.UserRepository; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.domain.TestUserFactory; +import com.evenly.took.global.security.auth.JwtTokenProvider; +import com.evenly.took.global.security.auth.UuidTokenProvider; import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; import com.evenly.took.global.security.client.UserClientComposite; -import com.evenly.took.global.security.jwt.JwtTokenProvider; import com.evenly.took.global.service.ServiceTest; class OAuthServiceTest extends ServiceTest { diff --git a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java index 385bf74..bdf837b 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java @@ -8,6 +8,7 @@ import com.evenly.took.global.exception.auth.oauth.InvalidRefreshTokenException; import com.evenly.took.global.redis.RedisService; +import com.evenly.took.global.security.auth.UuidTokenProvider; import com.evenly.took.global.service.ServiceTest; class UuidTokenProviderTest extends ServiceTest { diff --git a/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java index 3d3c3f9..9931b4e 100644 --- a/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java @@ -9,7 +9,7 @@ import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.config.properties.jwt.AuthProperties; import com.evenly.took.global.exception.TookException; -import com.evenly.took.global.security.jwt.JwtTokenProvider; +import com.evenly.took.global.security.auth.JwtTokenProvider; import com.evenly.took.global.service.MockTest; class JwtTokenProviderTest extends MockTest { From aef9b776fc341a26209465c008b3f28afba13072 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 26 Feb 2025 07:26:50 +0900 Subject: [PATCH 11/30] =?UTF-8?q?refac:=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../evenly/took/feature/auth/api/OAuthApi.java | 18 +++++++++++------- .../security/auth/AuthenticationFilter.java | 2 ++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java index f801700..e09fcdf 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java @@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -22,9 +23,10 @@ public interface OAuthApi { @Operation( summary = "소셜 로그인 인가 URL 리다이렉트", - description = "지정된 OAuthType에 따른 소셜 로그인 인가 코드 요청 URL로 클라이언트를 리다이렉트합니다." - ) - @ApiResponse(responseCode = "302", description = "리다이렉트 성공") + description = "지정된 OAuthType에 따른 소셜 로그인 인가 코드 요청 URL로 클라이언트를 리다이렉트합니다.") + @ApiResponse( + responseCode = "302", + description = "리다이렉트 성공") @GetMapping("/{oauthType}") void redirectAuthRequestUrl( @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @@ -32,10 +34,12 @@ void redirectAuthRequestUrl( HttpServletResponse response) throws IOException; @Operation( - summary = "소셜 로그인 및 JWT 토큰 발급", - description = "소셜 로그인 인가 코드를 통해 JWT 토큰(Access Token)을 발급받습니다." - ) - @ApiResponse(responseCode = "200", description = "로그인 성공", + summary = "소셜 로그인 및 토큰 발급", + description = "소셜 로그인 인가 코드를 통해 토큰(Access Token & Refresh Token)을 발급받습니다.") + @ApiResponse( + responseCode = "200", + description = "로그인 성공", + headers = @Header(name = "Authorization", description = "Bearer [access token] [refresh token]", required = true), content = @Content(schema = @Schema(implementation = SuccessResponse.class))) @GetMapping("/login/{oauthType}") SuccessResponse login( diff --git a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java index dff8b67..90e96ee 100644 --- a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java @@ -22,6 +22,8 @@ public class AuthenticationFilter extends OncePerRequestFilter { private static final List EXCLUDE_PATHS = List.of( + "/swagger-ui", + "/v3/api-docs", "/public", "/api/health", "/api/oauth/login"); From 57f96b2178bc153a8648c1b81bde0759cb65595d Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 15:31:49 +0900 Subject: [PATCH 12/30] =?UTF-8?q?refac:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/evenly/took/feature/user/domain/User.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/user/domain/User.java b/src/main/java/com/evenly/took/feature/user/domain/User.java index 3955070..bad5c7e 100644 --- a/src/main/java/com/evenly/took/feature/user/domain/User.java +++ b/src/main/java/com/evenly/took/feature/user/domain/User.java @@ -13,7 +13,6 @@ import jakarta.persistence.UniqueConstraint; import jakarta.validation.constraints.NotNull; import lombok.AccessLevel; -import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -26,7 +25,6 @@ ) }) @NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor @Getter public class User extends BaseTimeEntity { From 71c54b2cfe6f61affdc2670e824da524f2e4fc1f Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 16:25:58 +0900 Subject: [PATCH 13/30] =?UTF-8?q?refac:=20=EB=A0=88=EB=94=94=EC=8A=A4=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=B4=88=EA=B8=B0=ED=99=94=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../took/global/redis/RedisService.java | 5 --- .../took/global/redis/RedisServiceImpl.java | 6 ---- .../auth/application/OAuthServiceTest.java | 32 ++----------------- .../application/UuidTokenProviderTest.java | 6 ---- .../took/global/helper/RedisCleaner.java | 20 ++++++++++++ .../global/integration/IntegrationTest.java | 6 ++++ .../took/global/service/ServiceTest.java | 11 +++++++ 7 files changed, 40 insertions(+), 46 deletions(-) create mode 100644 src/test/java/com/evenly/took/global/helper/RedisCleaner.java diff --git a/src/main/java/com/evenly/took/global/redis/RedisService.java b/src/main/java/com/evenly/took/global/redis/RedisService.java index ebd81b7..1c52d8f 100644 --- a/src/main/java/com/evenly/took/global/redis/RedisService.java +++ b/src/main/java/com/evenly/took/global/redis/RedisService.java @@ -38,9 +38,4 @@ public interface RedisService { * @return 삭제 성공 여부 */ boolean deleteKey(String key); - - /** - * Redis에서 모든 key-value를 삭제합니다. - */ - void deleteAllKeys(); } diff --git a/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java b/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java index 2950511..9545dfb 100644 --- a/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java +++ b/src/main/java/com/evenly/took/global/redis/RedisServiceImpl.java @@ -46,12 +46,6 @@ public boolean deleteKey(String key) { }); } - public void deleteAllKeys() { - executeOperation(() -> { - redisTemplate.getConnectionFactory().getConnection().serverCommands().flushAll(); - }); - } - private boolean executeOperation(Runnable operation) { try { operation.run(); diff --git a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java b/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java index 627ee76..067cef2 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java @@ -4,50 +4,24 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.BDDMockito.*; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.dto.response.AuthResponse; -import com.evenly.took.feature.user.dao.UserRepository; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.domain.TestUserFactory; -import com.evenly.took.global.security.auth.JwtTokenProvider; -import com.evenly.took.global.security.auth.UuidTokenProvider; -import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; import com.evenly.took.global.security.client.UserClientComposite; import com.evenly.took.global.service.ServiceTest; class OAuthServiceTest extends ServiceTest { - OAuthService oauthService; - - @Mock + @MockitoBean UserClientComposite userClientComposite; - @Mock - AuthCodeRequestUrlProviderComposite authCodeComposite; - - @Autowired - UserRepository userRepository; - @Autowired - JwtTokenProvider jwtTokenProvider; - - @Autowired - UuidTokenProvider uuidTokenProvider; - - @BeforeEach - void setUp() { - oauthService = new OAuthService( - authCodeComposite, - userClientComposite, - userRepository, - jwtTokenProvider, - uuidTokenProvider); - } + OAuthService oauthService; @Test void 로그인시_토큰과_사용자_정보를_반환한다() { diff --git a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java index bdf837b..f05748e 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java @@ -2,7 +2,6 @@ import static org.assertj.core.api.Assertions.*; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -19,11 +18,6 @@ class UuidTokenProviderTest extends ServiceTest { @Autowired RedisService redisService; - @BeforeEach - void setUp() { - redisService.deleteAllKeys(); - } - @Test void 리프레쉬_토큰을_생성한다() { // given diff --git a/src/test/java/com/evenly/took/global/helper/RedisCleaner.java b/src/test/java/com/evenly/took/global/helper/RedisCleaner.java new file mode 100644 index 0000000..6cf9613 --- /dev/null +++ b/src/test/java/com/evenly/took/global/helper/RedisCleaner.java @@ -0,0 +1,20 @@ +package com.evenly.took.global.helper; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.test.context.ActiveProfiles; + +@Component +@ActiveProfiles("test") +public class RedisCleaner { + + private final RedisTemplate redisTemplate; + + public RedisCleaner(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + public void deleteAllKeys() { + redisTemplate.getConnectionFactory().getConnection().serverCommands().flushAll(); + } +} diff --git a/src/test/java/com/evenly/took/global/integration/IntegrationTest.java b/src/test/java/com/evenly/took/global/integration/IntegrationTest.java index 702e76d..73f494e 100644 --- a/src/test/java/com/evenly/took/global/integration/IntegrationTest.java +++ b/src/test/java/com/evenly/took/global/integration/IntegrationTest.java @@ -8,6 +8,7 @@ import org.springframework.test.context.ActiveProfiles; import com.evenly.took.global.config.testcontainers.RedisTestConfig; +import com.evenly.took.global.helper.RedisCleaner; import com.fasterxml.jackson.databind.ObjectMapper; import io.restassured.RestAssured; @@ -23,9 +24,14 @@ public abstract class IntegrationTest { @Autowired protected ObjectMapper objectMapper; + @Autowired + protected RedisCleaner redisCleaner; + @BeforeEach public void setUp() { RestAssured.baseURI = "http://localhost"; RestAssured.port = port; + + redisCleaner.deleteAllKeys(); } } diff --git a/src/test/java/com/evenly/took/global/service/ServiceTest.java b/src/test/java/com/evenly/took/global/service/ServiceTest.java index ab417e5..76782ee 100644 --- a/src/test/java/com/evenly/took/global/service/ServiceTest.java +++ b/src/test/java/com/evenly/took/global/service/ServiceTest.java @@ -1,13 +1,24 @@ package com.evenly.took.global.service; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; import com.evenly.took.global.config.testcontainers.RedisTestConfig; +import com.evenly.took.global.helper.RedisCleaner; @SpringBootTest @ActiveProfiles("test") @Import(RedisTestConfig.class) public abstract class ServiceTest { + + @Autowired + private RedisCleaner redisCleaner; + + @BeforeEach + public void setUp() { + redisCleaner.deleteAllKeys(); + } } From c037a0f065c462e5d522dd68a9ef88775d3bbfab Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 16:33:06 +0900 Subject: [PATCH 14/30] =?UTF-8?q?refac:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=9C=20=EC=9D=91=EB=8B=B5=20=ED=86=A0=ED=81=B0=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=ED=97=A4=EB=8D=94=20->=20=EB=B0=94=EB=94=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/evenly/took/feature/auth/api/OAuthApi.java | 3 +-- .../com/evenly/took/feature/auth/api/OAuthController.java | 7 ++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java index e09fcdf..aa76405 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java @@ -46,6 +46,5 @@ SuccessResponse login( @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @PathVariable OAuthType oauthType, @Parameter(description = "소셜 서버로부터 전달받은 인가 코드", required = true) - @RequestParam String code, - HttpServletResponse response); + @RequestParam String code); } diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java index 5563036..9ac8d4a 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java @@ -20,7 +20,6 @@ public class OAuthController implements OAuthApi { private final OAuthService oauthService; - private final HeaderHandler headerHandler; @GetMapping("/api/oauth/{oauthType}") public void redirectAuthRequestUrl( @@ -30,10 +29,8 @@ public void redirectAuthRequestUrl( } @GetMapping("/api/oauth/login/{oauthType}") - public SuccessResponse login( - @PathVariable OAuthType oauthType, @RequestParam String code, HttpServletResponse response) { + public SuccessResponse login(@PathVariable OAuthType oauthType, @RequestParam String code) { AuthResponse authResponse = oauthService.loginAndGenerateToken(oauthType, code); - headerHandler.setAuthHeader(response, authResponse.token()); - return SuccessResponse.of(authResponse.user()); + return SuccessResponse.of(authResponse); } } From 56f06c08f4e5cfa0d1f8215b8cc8fac3de1c6570 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 16:44:31 +0900 Subject: [PATCH 15/30] =?UTF-8?q?refac:=20oauth=20url=20API=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=ED=98=95=EC=8B=9D=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/evenly/took/feature/auth/api/OAuthApi.java | 8 ++------ .../took/feature/auth/api/OAuthController.java | 12 +++++------- .../took/feature/auth/application/OAuthService.java | 6 ++++-- .../feature/auth/dto/response/OAuthUrlResponse.java | 6 ++++++ 4 files changed, 17 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/evenly/took/feature/auth/dto/response/OAuthUrlResponse.java diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java index aa76405..3e9dffc 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java @@ -1,7 +1,5 @@ package com.evenly.took.feature.auth.api; -import java.io.IOException; - import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; @@ -16,7 +14,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.servlet.http.HttpServletResponse; @Tag(name = "[1. OAuth]") public interface OAuthApi { @@ -28,10 +25,9 @@ public interface OAuthApi { responseCode = "302", description = "리다이렉트 성공") @GetMapping("/{oauthType}") - void redirectAuthRequestUrl( + SuccessResponse redirectAuthRequestUrl( @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") - @PathVariable OAuthType oauthType, - HttpServletResponse response) throws IOException; + @PathVariable OAuthType oauthType); @Operation( summary = "소셜 로그인 및 토큰 발급", diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java index 9ac8d4a..5cad441 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java @@ -1,7 +1,6 @@ package com.evenly.took.feature.auth.api; -import java.io.IOException; - +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; @@ -10,9 +9,9 @@ import com.evenly.took.feature.auth.application.OAuthService; import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.dto.response.AuthResponse; +import com.evenly.took.feature.auth.dto.response.OAuthUrlResponse; import com.evenly.took.global.response.SuccessResponse; -import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; @RestController @@ -22,10 +21,9 @@ public class OAuthController implements OAuthApi { private final OAuthService oauthService; @GetMapping("/api/oauth/{oauthType}") - public void redirectAuthRequestUrl( - @PathVariable OAuthType oauthType, HttpServletResponse response) throws IOException { - String url = oauthService.getAuthCodeRequestUrl(oauthType); - response.sendRedirect(url); + public SuccessResponse redirectAuthRequestUrl(@PathVariable OAuthType oauthType) { + OAuthUrlResponse response = oauthService.getAuthCodeRequestUrl(oauthType); + return SuccessResponse.of(HttpStatus.FOUND, response); } @GetMapping("/api/oauth/login/{oauthType}") diff --git a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java index b93a7f6..730cca8 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java +++ b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java @@ -4,6 +4,7 @@ import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.dto.response.AuthResponse; +import com.evenly.took.feature.auth.dto.response.OAuthUrlResponse; import com.evenly.took.feature.user.dao.UserRepository; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.security.auth.JwtTokenProvider; @@ -23,8 +24,9 @@ public class OAuthService { private final JwtTokenProvider jwtTokenProvider; private final UuidTokenProvider uuidTokenProvider; - public String getAuthCodeRequestUrl(OAuthType oauthType) { - return authCodeComposite.provide(oauthType); + public OAuthUrlResponse getAuthCodeRequestUrl(OAuthType oauthType) { + String url = authCodeComposite.provide(oauthType); + return new OAuthUrlResponse(url); } public AuthResponse loginAndGenerateToken(OAuthType oauthType, String authCode) { diff --git a/src/main/java/com/evenly/took/feature/auth/dto/response/OAuthUrlResponse.java b/src/main/java/com/evenly/took/feature/auth/dto/response/OAuthUrlResponse.java new file mode 100644 index 0000000..4847aed --- /dev/null +++ b/src/main/java/com/evenly/took/feature/auth/dto/response/OAuthUrlResponse.java @@ -0,0 +1,6 @@ +package com.evenly.took.feature.auth.dto.response; + +public record OAuthUrlResponse( + String url +) { +} From 31b5fe3a3390c0b09c4f3c2d3010b582effbb638 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 17:35:48 +0900 Subject: [PATCH 16/30] =?UTF-8?q?test:=20=EC=9D=91=EB=8B=B5=20=ED=98=95?= =?UTF-8?q?=ED=83=9C=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../evenly/took/feature/auth/api/OAuthApi.java | 5 ++--- .../feature/auth/api/OAuthIntegrationTest.java | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java index 3e9dffc..4ca3b1e 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java @@ -9,7 +9,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.headers.Header; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -23,7 +22,8 @@ public interface OAuthApi { description = "지정된 OAuthType에 따른 소셜 로그인 인가 코드 요청 URL로 클라이언트를 리다이렉트합니다.") @ApiResponse( responseCode = "302", - description = "리다이렉트 성공") + description = "리다이렉트 성공", + content = @Content(schema = @Schema(implementation = SuccessResponse.class))) @GetMapping("/{oauthType}") SuccessResponse redirectAuthRequestUrl( @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @@ -35,7 +35,6 @@ SuccessResponse redirectAuthRequestUrl( @ApiResponse( responseCode = "200", description = "로그인 성공", - headers = @Header(name = "Authorization", description = "Bearer [access token] [refresh token]", required = true), content = @Content(schema = @Schema(implementation = SuccessResponse.class))) @GetMapping("/login/{oauthType}") SuccessResponse login( diff --git a/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java b/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java index 9b810ca..2072546 100644 --- a/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java +++ b/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java @@ -8,6 +8,7 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.domain.TestUserFactory; import com.evenly.took.global.integration.IntegrationTest; @@ -49,15 +50,17 @@ public class OAuthIntegrationTest extends IntegrationTest { BDDMockito.given(userClientComposite.fetch(any(OAuthType.class), anyString())) .willReturn(user); - String tokenHeader = given().log().all() + AuthResponse response = given().log().all() .when().get("/api/oauth/login/KAKAO?code=code") .then().log().all() .statusCode(200) .extract() - .header("Authorization"); + .body() + .jsonPath() + .getObject("data", AuthResponse.class); given().log().all() - .header("Authorization", "Bearer %s %s".formatted("invalid", tokenHeader.split(" ")[2])) + .header("Authorization", "Bearer %s %s".formatted("invalid", response.token().refreshToken())) .when().get("/api/test") .then().log().all() .statusCode(200); @@ -69,15 +72,18 @@ public class OAuthIntegrationTest extends IntegrationTest { BDDMockito.given(userClientComposite.fetch(any(OAuthType.class), anyString())) .willReturn(user); - String tokenHeader = given().log().all() + AuthResponse response = given().log().all() .when().get("/api/oauth/login/KAKAO?code=code") .then().log().all() .statusCode(200) .extract() - .header("Authorization"); + .body() + .jsonPath() + .getObject("data", AuthResponse.class); given().log().all() - .header("Authorization", tokenHeader) + .header("Authorization", + "Bearer %s %s".formatted(response.token().accessToken(), response.token().refreshToken())) .when().get("/api/test") .then().log().all() .statusCode(200); From 4a92e28b3ff9f89f0ca86e653635e5e621d0c243 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 18:42:19 +0900 Subject: [PATCH 17/30] =?UTF-8?q?feat:=20=EC=9D=91=EB=8B=B5=20DTO=20?= =?UTF-8?q?=EC=8A=A4=EC=9B=A8=EA=B1=B0=20=EC=84=A4=EB=AA=85=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../took/feature/auth/dto/response/AuthResponse.java | 7 +++++-- .../took/feature/auth/dto/response/TokenResponse.java | 7 +++++-- .../took/feature/auth/dto/response/UserResponse.java | 7 +++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java b/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java index 4230888..0681de9 100644 --- a/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java +++ b/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java @@ -2,9 +2,12 @@ import com.evenly.took.feature.user.domain.User; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "로그인 응답") public record AuthResponse( - TokenResponse token, - UserResponse user + @Schema(description = "액세스 토큰 및 리프레시 토큰 정보") TokenResponse token, + @Schema(description = "로그인 사용자 정보") UserResponse user ) { public AuthResponse(String accessToken, String refreshToken, User user) { diff --git a/src/main/java/com/evenly/took/feature/auth/dto/response/TokenResponse.java b/src/main/java/com/evenly/took/feature/auth/dto/response/TokenResponse.java index 3064002..20e44a3 100644 --- a/src/main/java/com/evenly/took/feature/auth/dto/response/TokenResponse.java +++ b/src/main/java/com/evenly/took/feature/auth/dto/response/TokenResponse.java @@ -1,7 +1,10 @@ package com.evenly.took.feature.auth.dto.response; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "로그인 토큰 정보") public record TokenResponse( - String accessToken, - String refreshToken + @Schema(description = "액세스 토큰 정보") String accessToken, + @Schema(description = "리프레시 토큰 정보") String refreshToken ) { } diff --git a/src/main/java/com/evenly/took/feature/auth/dto/response/UserResponse.java b/src/main/java/com/evenly/took/feature/auth/dto/response/UserResponse.java index 070b02a..8e00a75 100644 --- a/src/main/java/com/evenly/took/feature/auth/dto/response/UserResponse.java +++ b/src/main/java/com/evenly/took/feature/auth/dto/response/UserResponse.java @@ -2,9 +2,12 @@ import com.evenly.took.feature.user.domain.User; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "로그인 사용자 정보") public record UserResponse( - Long id, - String name + @Schema(description = "사용자 ID") Long id, + @Schema(description = "사용자 이름") String name ) { public UserResponse(User user) { From af5de97296e457af3f126391bfbc7b25e021168e Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 18:42:46 +0900 Subject: [PATCH 18/30] =?UTF-8?q?refac:=20=EA=B3=B5=ED=86=B5=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=ED=81=B4=EB=9E=98=EC=8A=A4=20data=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD=20Object=20?= =?UTF-8?q?->=20=EC=A0=9C=EB=84=A4=EB=A6=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/evenly/took/feature/auth/api/OAuthApi.java | 6 ++++-- .../took/feature/auth/api/OAuthController.java | 4 ++-- .../evenly/took/global/response/SuccessResponse.java | 12 ++++++------ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java index 4ca3b1e..cee0450 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java @@ -5,6 +5,8 @@ import org.springframework.web.bind.annotation.RequestParam; import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.auth.dto.response.AuthResponse; +import com.evenly.took.feature.auth.dto.response.OAuthUrlResponse; import com.evenly.took.global.response.SuccessResponse; import io.swagger.v3.oas.annotations.Operation; @@ -25,7 +27,7 @@ public interface OAuthApi { description = "리다이렉트 성공", content = @Content(schema = @Schema(implementation = SuccessResponse.class))) @GetMapping("/{oauthType}") - SuccessResponse redirectAuthRequestUrl( + SuccessResponse redirectAuthRequestUrl( @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @PathVariable OAuthType oauthType); @@ -37,7 +39,7 @@ SuccessResponse redirectAuthRequestUrl( description = "로그인 성공", content = @Content(schema = @Schema(implementation = SuccessResponse.class))) @GetMapping("/login/{oauthType}") - SuccessResponse login( + SuccessResponse login( // TODO 에러 응답 추가 @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @PathVariable OAuthType oauthType, @Parameter(description = "소셜 서버로부터 전달받은 인가 코드", required = true) diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java index 5cad441..5f21eb7 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java @@ -21,13 +21,13 @@ public class OAuthController implements OAuthApi { private final OAuthService oauthService; @GetMapping("/api/oauth/{oauthType}") - public SuccessResponse redirectAuthRequestUrl(@PathVariable OAuthType oauthType) { + public SuccessResponse redirectAuthRequestUrl(@PathVariable OAuthType oauthType) { OAuthUrlResponse response = oauthService.getAuthCodeRequestUrl(oauthType); return SuccessResponse.of(HttpStatus.FOUND, response); } @GetMapping("/api/oauth/login/{oauthType}") - public SuccessResponse login(@PathVariable OAuthType oauthType, @RequestParam String code) { + public SuccessResponse login(@PathVariable OAuthType oauthType, @RequestParam String code) { AuthResponse authResponse = oauthService.loginAndGenerateToken(oauthType, code); return SuccessResponse.of(authResponse); } diff --git a/src/main/java/com/evenly/took/global/response/SuccessResponse.java b/src/main/java/com/evenly/took/global/response/SuccessResponse.java index dce99cb..713ec27 100644 --- a/src/main/java/com/evenly/took/global/response/SuccessResponse.java +++ b/src/main/java/com/evenly/took/global/response/SuccessResponse.java @@ -10,7 +10,7 @@ @Getter @RequiredArgsConstructor(access = AccessLevel.PRIVATE) -public class SuccessResponse { +public class SuccessResponse { private static final HttpStatus DEFAULT_HTTP_STATUS = HttpStatus.OK; private static final String DEFAULT_MESSAGE = "요청이 성공적으로 처리되었습니다."; @@ -18,13 +18,13 @@ public class SuccessResponse { private final HttpStatus status; private final String message; private final LocalDateTime timestamp; - private final Object data; + private final T data; - public static SuccessResponse of(Object data) { - return new SuccessResponse(DEFAULT_HTTP_STATUS, DEFAULT_MESSAGE, LocalDateTime.now(), data); + public static SuccessResponse of(T data) { + return new SuccessResponse<>(DEFAULT_HTTP_STATUS, DEFAULT_MESSAGE, LocalDateTime.now(), data); } - public static SuccessResponse of(HttpStatus status, Object data) { - return new SuccessResponse(status, DEFAULT_MESSAGE, LocalDateTime.now(), data); + public static SuccessResponse of(HttpStatus status, T data) { + return new SuccessResponse<>(status, DEFAULT_MESSAGE, LocalDateTime.now(), data); } } From 7ad3a48dadcc2984c2aa341e007a71ee1c5b9dc4 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 19:57:02 +0900 Subject: [PATCH 19/30] =?UTF-8?q?refac:=20refresh=20token=20=EB=B0=9C?= =?UTF-8?q?=EA=B8=89=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존: AT 만료 시 함께 보낸 RT로 갱신 - 수정: AT 만료 시 /refresh API를 통해 갱신 --- .../took/feature/auth/api/HeaderHandler.java | 21 +-------- .../feature/auth/api/OAuthController.java | 13 +++++- .../auth/application/OAuthService.java | 10 +++-- .../auth/dto/request/RefreshTokenRequest.java | 6 +++ .../security/auth/AuthenticationFilter.java | 22 ++------- .../auth/api/OAuthIntegrationTest.java | 45 +++++++++++++------ .../feature/auth/api/TestAuthController.java | 2 + 7 files changed, 62 insertions(+), 57 deletions(-) create mode 100644 src/main/java/com/evenly/took/feature/auth/dto/request/RefreshTokenRequest.java diff --git a/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java b/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java index 6bb7118..6c5ceaa 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java +++ b/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java @@ -2,40 +2,21 @@ import org.springframework.stereotype.Component; -import com.evenly.took.feature.auth.dto.response.TokenResponse; import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; import com.evenly.took.global.exception.auth.oauth.InvalidTokenException; import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; @Component public class HeaderHandler { private static final String HEADER_KEY_OF_AUTH = "Authorization"; - private static final String HEADER_VALUE_FORMAT_OF_AUTH = "Bearer %s %s"; private static final String HEADER_VALUE_PREFIX_OF_AUTH = "Bearer "; - private static final String HEADER_VALUE_DELIMITER_OF_AUTH = " "; - - public void setAuthHeader(HttpServletResponse response, TokenResponse tokenResponse) { - String value = buildAuthHeaderValue(tokenResponse.accessToken(), tokenResponse.refreshToken()); - response.setHeader(HEADER_KEY_OF_AUTH, value); - } - - private String buildAuthHeaderValue(String accessToken, String refreshToken) { - return String.format(HEADER_VALUE_FORMAT_OF_AUTH, accessToken, refreshToken); - } public String resolveAccessToken(HttpServletRequest request) { String bearerToken = request.getHeader(HEADER_KEY_OF_AUTH); validateAuthHeader(bearerToken); - return bearerToken.split(HEADER_VALUE_DELIMITER_OF_AUTH)[1]; - } - - public String resolveRefreshToken(HttpServletRequest request) { - String bearerToken = request.getHeader(HEADER_KEY_OF_AUTH); - validateAuthHeader(bearerToken); - return bearerToken.split(HEADER_VALUE_DELIMITER_OF_AUTH)[2]; + return bearerToken.substring(HEADER_VALUE_PREFIX_OF_AUTH.length()); } private void validateAuthHeader(String bearerToken) { diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java index 5f21eb7..bb50736 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java +++ b/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java @@ -3,13 +3,16 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.evenly.took.feature.auth.application.OAuthService; import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.auth.dto.request.RefreshTokenRequest; import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.feature.auth.dto.response.OAuthUrlResponse; +import com.evenly.took.feature.auth.dto.response.TokenResponse; import com.evenly.took.global.response.SuccessResponse; import lombok.RequiredArgsConstructor; @@ -28,7 +31,13 @@ public SuccessResponse redirectAuthRequestUrl(@PathVariable OA @GetMapping("/api/oauth/login/{oauthType}") public SuccessResponse login(@PathVariable OAuthType oauthType, @RequestParam String code) { - AuthResponse authResponse = oauthService.loginAndGenerateToken(oauthType, code); - return SuccessResponse.of(authResponse); + AuthResponse response = oauthService.loginAndGenerateToken(oauthType, code); + return SuccessResponse.of(response); + } + + @GetMapping("/api/oauth/refresh") + public SuccessResponse refreshToken(@RequestBody RefreshTokenRequest request) { + TokenResponse response = oauthService.refreshToken(request); + return SuccessResponse.of(response); } } diff --git a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java index 730cca8..17d7bd3 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java +++ b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java @@ -3,8 +3,10 @@ import org.springframework.stereotype.Service; import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.auth.dto.request.RefreshTokenRequest; import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.feature.auth.dto.response.OAuthUrlResponse; +import com.evenly.took.feature.auth.dto.response.TokenResponse; import com.evenly.took.feature.user.dao.UserRepository; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.security.auth.JwtTokenProvider; @@ -34,9 +36,9 @@ public AuthResponse loginAndGenerateToken(OAuthType oauthType, String authCode) User savedUser = userRepository.findByOauthIdentifier(user.getOauthIdentifier()) .orElseGet(() -> userRepository.save(user)); - String accessToken = jwtTokenProvider.generateAccessToken(savedUser.getId().toString()); - String refreshToken = uuidTokenProvider.generateRefreshToken(savedUser.getId().toString()); - - return new AuthResponse(accessToken, refreshToken, user); + public TokenResponse refreshToken(RefreshTokenRequest request) { + String refreshToken = request.refreshToken(); + String accessToken = tokenProvider.provideAccessTokenByRefreshToken(refreshToken); + return new TokenResponse(accessToken, refreshToken); } } diff --git a/src/main/java/com/evenly/took/feature/auth/dto/request/RefreshTokenRequest.java b/src/main/java/com/evenly/took/feature/auth/dto/request/RefreshTokenRequest.java new file mode 100644 index 0000000..274f1b7 --- /dev/null +++ b/src/main/java/com/evenly/took/feature/auth/dto/request/RefreshTokenRequest.java @@ -0,0 +1,6 @@ +package com.evenly.took.feature.auth.dto.request; + +public record RefreshTokenRequest( + String refreshToken +) { +} diff --git a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java index 90e96ee..a726046 100644 --- a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java @@ -7,9 +7,7 @@ import org.springframework.web.filter.OncePerRequestFilter; import com.evenly.took.feature.auth.api.HeaderHandler; -import com.evenly.took.feature.auth.dto.response.TokenResponse; import com.evenly.took.global.exception.TookException; -import com.evenly.took.global.exception.auth.oauth.InvalidAccessTokenException; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; @@ -26,10 +24,9 @@ public class AuthenticationFilter extends OncePerRequestFilter { "/v3/api-docs", "/public", "/api/health", - "/api/oauth/login"); + "/api/oauth"); private final JwtTokenProvider jwtTokenProvider; - private final UuidTokenProvider uuidTokenProvider; private final HeaderHandler headerHandler; @Override @@ -45,26 +42,15 @@ protected void doFilterInternal( FilterChain filterChain) throws ServletException, IOException { try { - checkTokens(request, response); + checkTokens(request); filterChain.doFilter(request, response); } catch (TookException ex) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage()); // TODO 형식 통일 } } - private void checkTokens(HttpServletRequest request, HttpServletResponse response) { + private void checkTokens(HttpServletRequest request) { String accessToken = headerHandler.resolveAccessToken(request); - String refreshToken = headerHandler.resolveRefreshToken(request); - try { - jwtTokenProvider.validateToken(accessToken); - } catch (InvalidAccessTokenException ex) { - checkRefreshToken(refreshToken, response); - } - } - - private void checkRefreshToken(String refreshToken, HttpServletResponse response) { - String userId = uuidTokenProvider.getUserId(refreshToken); - String accessToken = jwtTokenProvider.generateAccessToken(userId); - headerHandler.setAuthHeader(response, new TokenResponse(accessToken, refreshToken)); + jwtTokenProvider.validateToken(accessToken); } } diff --git a/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java b/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java index 2072546..a68bda7 100644 --- a/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java +++ b/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java @@ -8,12 +8,15 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; import com.evenly.took.feature.auth.domain.OAuthType; -import com.evenly.took.feature.auth.dto.response.AuthResponse; +import com.evenly.took.feature.auth.dto.request.RefreshTokenRequest; +import com.evenly.took.feature.auth.dto.response.TokenResponse; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.domain.TestUserFactory; import com.evenly.took.global.integration.IntegrationTest; import com.evenly.took.global.security.client.UserClientComposite; +import io.restassured.http.ContentType; + public class OAuthIntegrationTest extends IntegrationTest { @MockitoBean @@ -32,58 +35,74 @@ public class OAuthIntegrationTest extends IntegrationTest { } @Test - void 유효하지_않은_액세스_토큰과_유효하지_않은_리프레쉬_토큰일_경우_401_예외를_반환한다() { + void 유효하지_않은_액세스_토큰으로_API를_요청할_경우_401_예외를_반환한다() { User user = TestUserFactory.createMockUser("took"); BDDMockito.given(userClientComposite.fetch(any(OAuthType.class), anyString())) .willReturn(user); given().log().all() - .header("Authorization", "Bearer invalid.access.token invalid-refresh-token") + .header("Authorization", "Bearer invalid.access.token") .when().get("/api/test") .then().log().all() .statusCode(401); } @Test - void 유효하지_않은_액세스_토큰과_유효한_리프레쉬_토큰일_경우_액세스_토큰을_갱신한다() { + void 토큰_갱신_요청시_유효한_리프레쉬_토큰일_경우_액세스_토큰을_갱신한다() { User user = TestUserFactory.createMockUser("took"); BDDMockito.given(userClientComposite.fetch(any(OAuthType.class), anyString())) .willReturn(user); - AuthResponse response = given().log().all() + TokenResponse tokens = given().log().all() .when().get("/api/oauth/login/KAKAO?code=code") .then().log().all() .statusCode(200) .extract() .body() .jsonPath() - .getObject("data", AuthResponse.class); + .getObject("data.token", TokenResponse.class); + RefreshTokenRequest request = new RefreshTokenRequest(tokens.refreshToken()); given().log().all() - .header("Authorization", "Bearer %s %s".formatted("invalid", response.token().refreshToken())) - .when().get("/api/test") + .contentType(ContentType.JSON) + .body(request) + .when().get("/api/oauth/refresh") .then().log().all() .statusCode(200); } @Test - void 유효한_액세스_토큰과_유효한_리프레쉬_토큰일_경우_예외를_반환하지_않는다() { + void 토큰_갱신_요청시_유효하지_않은_리프레쉬_토큰일_경우_401_예외를_반환한다() { + User user = TestUserFactory.createMockUser("took"); + BDDMockito.given(userClientComposite.fetch(any(OAuthType.class), anyString())) + .willReturn(user); + + RefreshTokenRequest request = new RefreshTokenRequest("invalid"); + given().log().all() + .contentType(ContentType.JSON) + .body(request) + .when().get("/api/oauth/refresh") + .then().log().all() + .statusCode(401); + } + + @Test + void 유효한_액세스_토큰으로_API를_요청할_경우_예외를_반환하지_않는다() { User user = TestUserFactory.createMockUser("took"); BDDMockito.given(userClientComposite.fetch(any(OAuthType.class), anyString())) .willReturn(user); - AuthResponse response = given().log().all() + TokenResponse tokens = given().log().all() .when().get("/api/oauth/login/KAKAO?code=code") .then().log().all() .statusCode(200) .extract() .body() .jsonPath() - .getObject("data", AuthResponse.class); + .getObject("data.token", TokenResponse.class); given().log().all() - .header("Authorization", - "Bearer %s %s".formatted(response.token().accessToken(), response.token().refreshToken())) + .header("Authorization", "Bearer %s".formatted(tokens.accessToken())) .when().get("/api/test") .then().log().all() .statusCode(200); diff --git a/src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java b/src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java index 676b7b3..7ec7c8d 100644 --- a/src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java +++ b/src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java @@ -1,8 +1,10 @@ package com.evenly.took.feature.auth.api; +import org.springframework.test.context.ActiveProfiles; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; +@ActiveProfiles("test") @RestController public class TestAuthController { From 7ad1105d5e22f75486679605831a784f493c13ef Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 19:58:05 +0900 Subject: [PATCH 20/30] =?UTF-8?q?refac:=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EA=B3=84=EC=B8=B5=EC=9D=98=20=EC=B1=85=EC=9E=84=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=B4=20TokenProvider=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/OAuthService.java | 9 +++--- .../auth/application/TokenProvider.java | 29 +++++++++++++++++++ .../took/feature/auth/dto/TokenDto.java | 7 +++++ .../auth/dto/response/AuthResponse.java | 6 ++-- 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java create mode 100644 src/main/java/com/evenly/took/feature/auth/dto/TokenDto.java diff --git a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java index 17d7bd3..6d0bee2 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java +++ b/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java @@ -3,14 +3,13 @@ import org.springframework.stereotype.Service; import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.auth.dto.TokenDto; import com.evenly.took.feature.auth.dto.request.RefreshTokenRequest; import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.feature.auth.dto.response.OAuthUrlResponse; import com.evenly.took.feature.auth.dto.response.TokenResponse; import com.evenly.took.feature.user.dao.UserRepository; import com.evenly.took.feature.user.domain.User; -import com.evenly.took.global.security.auth.JwtTokenProvider; -import com.evenly.took.global.security.auth.UuidTokenProvider; import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; import com.evenly.took.global.security.client.UserClientComposite; @@ -23,8 +22,7 @@ public class OAuthService { private final AuthCodeRequestUrlProviderComposite authCodeComposite; private final UserClientComposite userClientComposite; private final UserRepository userRepository; - private final JwtTokenProvider jwtTokenProvider; - private final UuidTokenProvider uuidTokenProvider; + private final TokenProvider tokenProvider; public OAuthUrlResponse getAuthCodeRequestUrl(OAuthType oauthType) { String url = authCodeComposite.provide(oauthType); @@ -35,6 +33,9 @@ public AuthResponse loginAndGenerateToken(OAuthType oauthType, String authCode) User user = userClientComposite.fetch(oauthType, authCode); User savedUser = userRepository.findByOauthIdentifier(user.getOauthIdentifier()) .orElseGet(() -> userRepository.save(user)); + TokenDto tokens = tokenProvider.provideTokens(savedUser); + return new AuthResponse(tokens, user); + } public TokenResponse refreshToken(RefreshTokenRequest request) { String refreshToken = request.refreshToken(); diff --git a/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java new file mode 100644 index 0000000..ca56613 --- /dev/null +++ b/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java @@ -0,0 +1,29 @@ +package com.evenly.took.feature.auth.application; + +import org.springframework.stereotype.Component; + +import com.evenly.took.feature.auth.dto.TokenDto; +import com.evenly.took.feature.user.domain.User; +import com.evenly.took.global.security.auth.JwtTokenProvider; +import com.evenly.took.global.security.auth.UuidTokenProvider; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class TokenProvider { + + private final JwtTokenProvider jwtTokenProvider; + private final UuidTokenProvider uuidTokenProvider; + + public TokenDto provideTokens(User user) { + String accessToken = jwtTokenProvider.generateAccessToken(user.getId().toString()); + String refreshToken = uuidTokenProvider.generateRefreshToken(user.getId().toString()); + return new TokenDto(accessToken, refreshToken); + } + + public String provideAccessTokenByRefreshToken(String refreshToken) { + String userId = uuidTokenProvider.getUserId(refreshToken); + return jwtTokenProvider.generateAccessToken(userId); + } +} diff --git a/src/main/java/com/evenly/took/feature/auth/dto/TokenDto.java b/src/main/java/com/evenly/took/feature/auth/dto/TokenDto.java new file mode 100644 index 0000000..41f1118 --- /dev/null +++ b/src/main/java/com/evenly/took/feature/auth/dto/TokenDto.java @@ -0,0 +1,7 @@ +package com.evenly.took.feature.auth.dto; + +public record TokenDto( + String accessToken, + String refreshToken +) { +} diff --git a/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java b/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java index 0681de9..4e0c637 100644 --- a/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java +++ b/src/main/java/com/evenly/took/feature/auth/dto/response/AuthResponse.java @@ -1,5 +1,6 @@ package com.evenly.took.feature.auth.dto.response; +import com.evenly.took.feature.auth.dto.TokenDto; import com.evenly.took.feature.user.domain.User; import io.swagger.v3.oas.annotations.media.Schema; @@ -10,7 +11,8 @@ public record AuthResponse( @Schema(description = "로그인 사용자 정보") UserResponse user ) { - public AuthResponse(String accessToken, String refreshToken, User user) { - this(new TokenResponse(accessToken, refreshToken), new UserResponse(user)); + public AuthResponse(TokenDto tokens, User user) { + this(new TokenResponse(tokens.accessToken(), tokens.refreshToken()), + new UserResponse(user)); } } From ab11995aa827f384b25bead9645b720ca2d6dd81 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 20:00:44 +0900 Subject: [PATCH 21/30] =?UTF-8?q?refac:=20Auth=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=ED=86=B5=ED=95=A9=20=EB=B0=8F=20static=20?= =?UTF-8?q?import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/auth/jwt/AuthErrorCode.java | 2 +- .../exception/auth/oauth/OAuthErrorCode.java | 19 ------------------- .../security/auth/JwtTokenProvider.java | 6 ++---- .../AuthCodeRequestUrlProviderComposite.java | 5 ++--- .../security/client/UserClientComposite.java | 5 ++--- ...thCodeRequestUrlProviderCompositeTest.java | 5 +++-- 6 files changed, 10 insertions(+), 32 deletions(-) delete mode 100644 src/main/java/com/evenly/took/global/exception/auth/oauth/OAuthErrorCode.java diff --git a/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java b/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java index 0e93bcb..7210d93 100644 --- a/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java +++ b/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java @@ -11,9 +11,9 @@ @RequiredArgsConstructor public enum AuthErrorCode implements ErrorCode { + OAUTH_TYPE_NOT_FOUND(HttpStatus.NOT_FOUND, "OAuth 타입을 찾을 수 없습니다."), JWT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "JWT를 찾을 수 없습니다."), EXPIRED_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "refresh token이 만료되었습니다."), - INVALID_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "refresh token이 유효하지 않습니다."), INVALID_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, "access token이 유효하지 않습니다."), ; diff --git a/src/main/java/com/evenly/took/global/exception/auth/oauth/OAuthErrorCode.java b/src/main/java/com/evenly/took/global/exception/auth/oauth/OAuthErrorCode.java deleted file mode 100644 index 06384eb..0000000 --- a/src/main/java/com/evenly/took/global/exception/auth/oauth/OAuthErrorCode.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.evenly.took.global.exception.auth.oauth; - -import org.springframework.http.HttpStatus; - -import com.evenly.took.global.exception.ErrorCode; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum OAuthErrorCode implements ErrorCode { - - OAUTH_TYPE_NOT_FOUND(HttpStatus.NOT_FOUND, "OAuth 타입을 찾을 수 없습니다."), - ; - - private final HttpStatus status; - private final String message; -} diff --git a/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java b/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java index a67ddcc..2063a92 100644 --- a/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java +++ b/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java @@ -1,7 +1,5 @@ package com.evenly.took.global.security.auth; -import static com.evenly.took.global.exception.auth.jwt.AuthErrorCode.*; - import java.nio.charset.StandardCharsets; import java.security.Key; import java.util.Date; @@ -54,8 +52,8 @@ public void validateToken(String token) { try { parseClaims(token); } catch (JwtException | IllegalArgumentException e) { - log.error(JWT_UNAUTHORIZED.getMessage(), e); - throw new InvalidAccessTokenException(JWT_UNAUTHORIZED); + log.error(AuthErrorCode.JWT_UNAUTHORIZED.getMessage(), e); + throw new InvalidAccessTokenException(AuthErrorCode.JWT_UNAUTHORIZED); } } diff --git a/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java b/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java index 3dfb59a..44b49f3 100644 --- a/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java +++ b/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java @@ -1,7 +1,5 @@ package com.evenly.took.global.security.client; -import static com.evenly.took.global.exception.auth.oauth.OAuthErrorCode.*; - import java.util.Map; import java.util.Optional; import java.util.Set; @@ -11,6 +9,7 @@ import org.springframework.stereotype.Component; import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; import com.evenly.took.global.exception.auth.oauth.OAuthTypeNotFoundException; @Component @@ -25,7 +24,7 @@ public AuthCodeRequestUrlProviderComposite(Set provi public String provide(OAuthType oauthType) { return Optional.ofNullable(mapping.get(oauthType)) - .orElseThrow(() -> new OAuthTypeNotFoundException(OAUTH_TYPE_NOT_FOUND)) + .orElseThrow(() -> new OAuthTypeNotFoundException(AuthErrorCode.OAUTH_TYPE_NOT_FOUND)) .provide(); } } diff --git a/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java b/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java index 382c15f..728422b 100644 --- a/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java +++ b/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java @@ -1,7 +1,5 @@ package com.evenly.took.global.security.client; -import static com.evenly.took.global.exception.auth.oauth.OAuthErrorCode.*; - import java.util.Map; import java.util.Optional; import java.util.Set; @@ -12,6 +10,7 @@ import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.user.domain.User; +import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; import com.evenly.took.global.exception.auth.oauth.OAuthTypeNotFoundException; @Component @@ -26,7 +25,7 @@ public UserClientComposite(Set clients) { public User fetch(OAuthType oauthType, String authCode) { return Optional.ofNullable(mapping.get(oauthType)) - .orElseThrow(() -> new OAuthTypeNotFoundException(OAUTH_TYPE_NOT_FOUND)) + .orElseThrow(() -> new OAuthTypeNotFoundException(AuthErrorCode.OAUTH_TYPE_NOT_FOUND)) .fetch(authCode); } } diff --git a/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java b/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java index bd8cbdd..7139247 100644 --- a/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java +++ b/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; import com.evenly.took.feature.auth.domain.OAuthType; -import com.evenly.took.global.exception.auth.oauth.OAuthErrorCode; +import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; import com.evenly.took.global.exception.auth.oauth.OAuthTypeNotFoundException; import com.evenly.took.global.security.client.AuthCodeRequestUrlProvider; import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; @@ -48,11 +48,12 @@ void setUp() { }); // then - assertThat(exception.getErrorCode()).isEqualTo(OAuthErrorCode.OAUTH_TYPE_NOT_FOUND); + assertThat(exception.getErrorCode()).isEqualTo(AuthErrorCode.OAUTH_TYPE_NOT_FOUND); } } class MockGoogleAuthCodeRequestUrlProvider implements AuthCodeRequestUrlProvider { + @Override public OAuthType supportType() { return OAuthType.GOOGLE; From bfc7fbc435dedf5d70b930bc74fd378ddd2a47c4 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 27 Feb 2025 20:13:20 +0900 Subject: [PATCH 22/30] =?UTF-8?q?refac:=20=EC=BB=A4=EB=B0=8B=207ad1105d=20?= =?UTF-8?q?=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../evenly/took/feature/auth/application/TokenProvider.java | 4 ++++ .../took/global/security/auth/AuthenticationFilter.java | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java index ca56613..e8e111a 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java +++ b/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java @@ -16,6 +16,10 @@ public class TokenProvider { private final JwtTokenProvider jwtTokenProvider; private final UuidTokenProvider uuidTokenProvider; + public void validateAccessToken(String accessToken) { + jwtTokenProvider.validateToken(accessToken); + } + public TokenDto provideTokens(User user) { String accessToken = jwtTokenProvider.generateAccessToken(user.getId().toString()); String refreshToken = uuidTokenProvider.generateRefreshToken(user.getId().toString()); diff --git a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java index a726046..63ef998 100644 --- a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java @@ -7,6 +7,7 @@ import org.springframework.web.filter.OncePerRequestFilter; import com.evenly.took.feature.auth.api.HeaderHandler; +import com.evenly.took.feature.auth.application.TokenProvider; import com.evenly.took.global.exception.TookException; import jakarta.servlet.FilterChain; @@ -26,7 +27,7 @@ public class AuthenticationFilter extends OncePerRequestFilter { "/api/health", "/api/oauth"); - private final JwtTokenProvider jwtTokenProvider; + private final TokenProvider tokenProvider; private final HeaderHandler headerHandler; @Override @@ -51,6 +52,6 @@ protected void doFilterInternal( private void checkTokens(HttpServletRequest request) { String accessToken = headerHandler.resolveAccessToken(request); - jwtTokenProvider.validateToken(accessToken); + tokenProvider.validateAccessToken(accessToken); } } From 65c6684be8aad3c44961ea76a00790594cab4377 Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 28 Feb 2025 00:11:26 +0900 Subject: [PATCH 23/30] =?UTF-8?q?refac:=20filter=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=ED=98=95=ED=83=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/auth/jwt/AuthErrorCode.java | 1 + .../global/exception/dto/ErrorResponse.java | 10 +++++-- .../took/global/response/SuccessResponse.java | 3 ++ .../security/auth/AuthenticationFilter.java | 29 +++++++++++++++++-- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java b/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java index 7210d93..58129aa 100644 --- a/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java +++ b/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java @@ -14,6 +14,7 @@ public enum AuthErrorCode implements ErrorCode { OAUTH_TYPE_NOT_FOUND(HttpStatus.NOT_FOUND, "OAuth 타입을 찾을 수 없습니다."), JWT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "JWT를 찾을 수 없습니다."), EXPIRED_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "refresh token이 만료되었습니다."), + EXPIRED_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, "access token이 만료되었습니다."), INVALID_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, "access token이 유효하지 않습니다."), ; diff --git a/src/main/java/com/evenly/took/global/exception/dto/ErrorResponse.java b/src/main/java/com/evenly/took/global/exception/dto/ErrorResponse.java index fa66b41..c3d3289 100644 --- a/src/main/java/com/evenly/took/global/exception/dto/ErrorResponse.java +++ b/src/main/java/com/evenly/took/global/exception/dto/ErrorResponse.java @@ -5,15 +5,19 @@ import org.springframework.http.HttpStatus; import com.evenly.took.global.exception.ErrorCode; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter +@NoArgsConstructor public class ErrorResponse { - private final HttpStatus status; - private final String message; - private final LocalDateTime timestamp; + private HttpStatus status; + private String message; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime timestamp; protected ErrorResponse(ErrorCode errorCode) { this.status = errorCode.getStatus(); diff --git a/src/main/java/com/evenly/took/global/response/SuccessResponse.java b/src/main/java/com/evenly/took/global/response/SuccessResponse.java index 713ec27..5d47a93 100644 --- a/src/main/java/com/evenly/took/global/response/SuccessResponse.java +++ b/src/main/java/com/evenly/took/global/response/SuccessResponse.java @@ -4,6 +4,8 @@ import org.springframework.http.HttpStatus; +import com.fasterxml.jackson.annotation.JsonFormat; + import lombok.AccessLevel; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -17,6 +19,7 @@ public class SuccessResponse { private final HttpStatus status; private final String message; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") private final LocalDateTime timestamp; private final T data; diff --git a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java index 63ef998..7f54114 100644 --- a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java @@ -1,14 +1,21 @@ package com.evenly.took.global.security.auth; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.List; +import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import com.evenly.took.feature.auth.api.HeaderHandler; import com.evenly.took.feature.auth.application.TokenProvider; +import com.evenly.took.global.exception.ErrorCode; import com.evenly.took.global.exception.TookException; +import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; +import com.evenly.took.global.exception.dto.ErrorResponse; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; @@ -20,6 +27,7 @@ @RequiredArgsConstructor public class AuthenticationFilter extends OncePerRequestFilter { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final List EXCLUDE_PATHS = List.of( "/swagger-ui", "/v3/api-docs", @@ -27,8 +35,12 @@ public class AuthenticationFilter extends OncePerRequestFilter { "/api/health", "/api/oauth"); - private final TokenProvider tokenProvider; + static { + OBJECT_MAPPER.registerModule(new JavaTimeModule()); + } + private final HeaderHandler headerHandler; + private final TokenProvider tokenProvider; @Override protected boolean shouldNotFilter(HttpServletRequest request) { @@ -46,7 +58,8 @@ protected void doFilterInternal( checkTokens(request); filterChain.doFilter(request, response); } catch (TookException ex) { - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage()); // TODO 형식 통일 + AuthErrorCode errorCode = AuthErrorCode.EXPIRED_ACCESS_TOKEN; + sendError(response, errorCode); } } @@ -54,4 +67,16 @@ private void checkTokens(HttpServletRequest request) { String accessToken = headerHandler.resolveAccessToken(request); tokenProvider.validateAccessToken(accessToken); } + + private void sendError(HttpServletResponse response, ErrorCode errorCode) throws IOException { + response.setStatus(errorCode.getStatus().value()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding(StandardCharsets.UTF_8.displayName()); + String body = serialize(ErrorResponse.of(errorCode)); + response.getWriter().write(body); + } + + private String serialize(ErrorResponse responseBody) throws IOException { + return OBJECT_MAPPER.writeValueAsString(responseBody); + } } From e20efb89066c0058ac3c7c145c69c3c48d58e452 Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 28 Feb 2025 21:28:21 +0900 Subject: [PATCH 24/30] =?UTF-8?q?refac:=20=EC=9D=B8=EC=A6=9D=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EC=9A=A9=EC=96=B4=20=ED=86=B5=EC=9D=BC=20?= =?UTF-8?q?oauth=20->=20auth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/{OAuthApi.java => AuthApi.java} | 10 ++++++---- ...AuthController.java => AuthController.java} | 18 +++++++++--------- .../{OAuthService.java => AuthService.java} | 2 +- .../security/auth/AuthenticationFilter.java | 2 +- ...ationTest.java => AuthIntegrationTest.java} | 12 ++++++------ ...AuthController.java => TestController.java} | 2 +- ...thServiceTest.java => AuthServiceTest.java} | 6 +++--- 7 files changed, 27 insertions(+), 25 deletions(-) rename src/main/java/com/evenly/took/feature/auth/api/{OAuthApi.java => AuthApi.java} (92%) rename src/main/java/com/evenly/took/feature/auth/api/{OAuthController.java => AuthController.java} (72%) rename src/main/java/com/evenly/took/feature/auth/application/{OAuthService.java => AuthService.java} (98%) rename src/test/java/com/evenly/took/feature/auth/api/{OAuthIntegrationTest.java => AuthIntegrationTest.java} (91%) rename src/test/java/com/evenly/took/feature/auth/api/{TestAuthController.java => TestController.java} (90%) rename src/test/java/com/evenly/took/feature/auth/application/{OAuthServiceTest.java => AuthServiceTest.java} (88%) diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java b/src/main/java/com/evenly/took/feature/auth/api/AuthApi.java similarity index 92% rename from src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java rename to src/main/java/com/evenly/took/feature/auth/api/AuthApi.java index cee0450..89eab1c 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthApi.java +++ b/src/main/java/com/evenly/took/feature/auth/api/AuthApi.java @@ -16,8 +16,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -@Tag(name = "[1. OAuth]") -public interface OAuthApi { +@Tag(name = "[1. Auth]") +public interface AuthApi { @Operation( summary = "소셜 로그인 인가 URL 리다이렉트", @@ -26,7 +26,7 @@ public interface OAuthApi { responseCode = "302", description = "리다이렉트 성공", content = @Content(schema = @Schema(implementation = SuccessResponse.class))) - @GetMapping("/{oauthType}") + @GetMapping("/api/auth/{oauthType}") SuccessResponse redirectAuthRequestUrl( @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @PathVariable OAuthType oauthType); @@ -38,10 +38,12 @@ SuccessResponse redirectAuthRequestUrl( responseCode = "200", description = "로그인 성공", content = @Content(schema = @Schema(implementation = SuccessResponse.class))) - @GetMapping("/login/{oauthType}") + @GetMapping("/api/auth/login/{oauthType}") SuccessResponse login( // TODO 에러 응답 추가 @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @PathVariable OAuthType oauthType, @Parameter(description = "소셜 서버로부터 전달받은 인가 코드", required = true) @RequestParam String code); + + // TODO refresh API 추가 } diff --git a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java b/src/main/java/com/evenly/took/feature/auth/api/AuthController.java similarity index 72% rename from src/main/java/com/evenly/took/feature/auth/api/OAuthController.java rename to src/main/java/com/evenly/took/feature/auth/api/AuthController.java index bb50736..983adb1 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/OAuthController.java +++ b/src/main/java/com/evenly/took/feature/auth/api/AuthController.java @@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import com.evenly.took.feature.auth.application.OAuthService; +import com.evenly.took.feature.auth.application.AuthService; import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.dto.request.RefreshTokenRequest; import com.evenly.took.feature.auth.dto.response.AuthResponse; @@ -19,25 +19,25 @@ @RestController @RequiredArgsConstructor -public class OAuthController implements OAuthApi { +public class AuthController implements AuthApi { - private final OAuthService oauthService; + private final AuthService authService; - @GetMapping("/api/oauth/{oauthType}") + @GetMapping("/api/auth/{oauthType}") public SuccessResponse redirectAuthRequestUrl(@PathVariable OAuthType oauthType) { - OAuthUrlResponse response = oauthService.getAuthCodeRequestUrl(oauthType); + OAuthUrlResponse response = authService.getAuthCodeRequestUrl(oauthType); return SuccessResponse.of(HttpStatus.FOUND, response); } - @GetMapping("/api/oauth/login/{oauthType}") + @GetMapping("/api/auth/login/{oauthType}") public SuccessResponse login(@PathVariable OAuthType oauthType, @RequestParam String code) { - AuthResponse response = oauthService.loginAndGenerateToken(oauthType, code); + AuthResponse response = authService.loginAndGenerateToken(oauthType, code); return SuccessResponse.of(response); } - @GetMapping("/api/oauth/refresh") + @GetMapping("/api/auth/refresh") public SuccessResponse refreshToken(@RequestBody RefreshTokenRequest request) { - TokenResponse response = oauthService.refreshToken(request); + TokenResponse response = authService.refreshToken(request); return SuccessResponse.of(response); } } diff --git a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java b/src/main/java/com/evenly/took/feature/auth/application/AuthService.java similarity index 98% rename from src/main/java/com/evenly/took/feature/auth/application/OAuthService.java rename to src/main/java/com/evenly/took/feature/auth/application/AuthService.java index 6d0bee2..b1199cd 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/OAuthService.java +++ b/src/main/java/com/evenly/took/feature/auth/application/AuthService.java @@ -17,7 +17,7 @@ @Service @RequiredArgsConstructor -public class OAuthService { +public class AuthService { private final AuthCodeRequestUrlProviderComposite authCodeComposite; private final UserClientComposite userClientComposite; diff --git a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java index 7f54114..fda9e45 100644 --- a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java @@ -33,7 +33,7 @@ public class AuthenticationFilter extends OncePerRequestFilter { "/v3/api-docs", "/public", "/api/health", - "/api/oauth"); + "/api/auth"); static { OBJECT_MAPPER.registerModule(new JavaTimeModule()); diff --git a/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java b/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java similarity index 91% rename from src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java rename to src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java index a68bda7..145942f 100644 --- a/src/test/java/com/evenly/took/feature/auth/api/OAuthIntegrationTest.java +++ b/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java @@ -17,7 +17,7 @@ import io.restassured.http.ContentType; -public class OAuthIntegrationTest extends IntegrationTest { +public class AuthIntegrationTest extends IntegrationTest { @MockitoBean UserClientComposite userClientComposite; @@ -29,7 +29,7 @@ public class OAuthIntegrationTest extends IntegrationTest { .willReturn(user); given().log().all() - .when().get("/api/oauth/login/KAKAO?code=code") + .when().get("/api/auth/login/KAKAO?code=code") .then().log().all() .statusCode(200); } @@ -54,7 +54,7 @@ public class OAuthIntegrationTest extends IntegrationTest { .willReturn(user); TokenResponse tokens = given().log().all() - .when().get("/api/oauth/login/KAKAO?code=code") + .when().get("/api/auth/login/KAKAO?code=code") .then().log().all() .statusCode(200) .extract() @@ -66,7 +66,7 @@ public class OAuthIntegrationTest extends IntegrationTest { given().log().all() .contentType(ContentType.JSON) .body(request) - .when().get("/api/oauth/refresh") + .when().get("/api/auth/refresh") .then().log().all() .statusCode(200); } @@ -81,7 +81,7 @@ public class OAuthIntegrationTest extends IntegrationTest { given().log().all() .contentType(ContentType.JSON) .body(request) - .when().get("/api/oauth/refresh") + .when().get("/api/auth/refresh") .then().log().all() .statusCode(401); } @@ -93,7 +93,7 @@ public class OAuthIntegrationTest extends IntegrationTest { .willReturn(user); TokenResponse tokens = given().log().all() - .when().get("/api/oauth/login/KAKAO?code=code") + .when().get("/api/auth/login/KAKAO?code=code") .then().log().all() .statusCode(200) .extract() diff --git a/src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java b/src/test/java/com/evenly/took/feature/auth/api/TestController.java similarity index 90% rename from src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java rename to src/test/java/com/evenly/took/feature/auth/api/TestController.java index 7ec7c8d..a1c20c0 100644 --- a/src/test/java/com/evenly/took/feature/auth/api/TestAuthController.java +++ b/src/test/java/com/evenly/took/feature/auth/api/TestController.java @@ -6,7 +6,7 @@ @ActiveProfiles("test") @RestController -public class TestAuthController { +public class TestController { @GetMapping("/api/test") public void test() { diff --git a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java b/src/test/java/com/evenly/took/feature/auth/application/AuthServiceTest.java similarity index 88% rename from src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java rename to src/test/java/com/evenly/took/feature/auth/application/AuthServiceTest.java index 067cef2..37c7239 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/OAuthServiceTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/AuthServiceTest.java @@ -15,13 +15,13 @@ import com.evenly.took.global.security.client.UserClientComposite; import com.evenly.took.global.service.ServiceTest; -class OAuthServiceTest extends ServiceTest { +class AuthServiceTest extends ServiceTest { @MockitoBean UserClientComposite userClientComposite; @Autowired - OAuthService oauthService; + AuthService authService; @Test void 로그인시_토큰과_사용자_정보를_반환한다() { @@ -31,7 +31,7 @@ class OAuthServiceTest extends ServiceTest { .willReturn(user); // when - AuthResponse response = oauthService.loginAndGenerateToken(OAuthType.KAKAO, "code"); + AuthResponse response = authService.loginAndGenerateToken(OAuthType.KAKAO, "code"); // then assertThat(response.token().accessToken()).containsAnyOf("."); From 9902ae26f4245a0c2809fbfc997f911e4212755a Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 28 Feb 2025 21:56:26 +0900 Subject: [PATCH 25/30] =?UTF-8?q?refac:=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존: global > exception > [feature] - 개선: [feature] > exception --- .../java/com/evenly/took/feature/auth/api/HeaderHandler.java | 4 ++-- .../auth/jwt => feature/auth/exception}/AuthErrorCode.java | 2 +- .../auth/exception}/InvalidAccessTokenException.java | 4 ++-- .../auth/exception}/InvalidRefreshTokenException.java | 4 ++-- .../auth/exception}/InvalidTokenException.java | 4 ++-- .../auth/exception}/OAuthTypeNotFoundException.java | 4 ++-- .../{global => feature/common}/exception/CommonErrorCode.java | 4 +++- .../{global => feature/common}/exception/TookException.java | 4 +++- .../evenly/took/global/exception/GlobalExceptionHandler.java | 2 ++ .../took/global/security/auth/AuthenticationFilter.java | 4 ++-- .../evenly/took/global/security/auth/JwtTokenProvider.java | 4 ++-- .../evenly/took/global/security/auth/UuidTokenProvider.java | 4 ++-- .../security/client/AuthCodeRequestUrlProviderComposite.java | 4 ++-- .../took/global/security/client/UserClientComposite.java | 4 ++-- .../took/feature/auth/application/UuidTokenProviderTest.java | 2 +- .../took/feature/auth/client/UserClientCompositeTest.java | 2 +- .../authcode/AuthCodeRequestUrlProviderCompositeTest.java | 4 ++-- .../evenly/took/feature/auth/jwt/JwtTokenProviderTest.java | 2 +- 18 files changed, 34 insertions(+), 28 deletions(-) rename src/main/java/com/evenly/took/{global/exception/auth/jwt => feature/auth/exception}/AuthErrorCode.java (93%) rename src/main/java/com/evenly/took/{global/exception/auth/oauth => feature/auth/exception}/InvalidAccessTokenException.java (68%) rename src/main/java/com/evenly/took/{global/exception/auth/oauth => feature/auth/exception}/InvalidRefreshTokenException.java (68%) rename src/main/java/com/evenly/took/{global/exception/auth/oauth => feature/auth/exception}/InvalidTokenException.java (67%) rename src/main/java/com/evenly/took/{global/exception/auth/oauth => feature/auth/exception}/OAuthTypeNotFoundException.java (67%) rename src/main/java/com/evenly/took/{global => feature/common}/exception/CommonErrorCode.java (84%) rename src/main/java/com/evenly/took/{global => feature/common}/exception/TookException.java (63%) diff --git a/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java b/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java index 6c5ceaa..5888e9f 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java +++ b/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java @@ -2,8 +2,8 @@ import org.springframework.stereotype.Component; -import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; -import com.evenly.took.global.exception.auth.oauth.InvalidTokenException; +import com.evenly.took.feature.auth.exception.AuthErrorCode; +import com.evenly.took.feature.auth.exception.InvalidTokenException; import jakarta.servlet.http.HttpServletRequest; diff --git a/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java b/src/main/java/com/evenly/took/feature/auth/exception/AuthErrorCode.java similarity index 93% rename from src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java rename to src/main/java/com/evenly/took/feature/auth/exception/AuthErrorCode.java index 58129aa..8e5f358 100644 --- a/src/main/java/com/evenly/took/global/exception/auth/jwt/AuthErrorCode.java +++ b/src/main/java/com/evenly/took/feature/auth/exception/AuthErrorCode.java @@ -1,4 +1,4 @@ -package com.evenly.took.global.exception.auth.jwt; +package com.evenly.took.feature.auth.exception; import org.springframework.http.HttpStatus; diff --git a/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidAccessTokenException.java b/src/main/java/com/evenly/took/feature/auth/exception/InvalidAccessTokenException.java similarity index 68% rename from src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidAccessTokenException.java rename to src/main/java/com/evenly/took/feature/auth/exception/InvalidAccessTokenException.java index 64b225e..9f5d992 100644 --- a/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidAccessTokenException.java +++ b/src/main/java/com/evenly/took/feature/auth/exception/InvalidAccessTokenException.java @@ -1,7 +1,7 @@ -package com.evenly.took.global.exception.auth.oauth; +package com.evenly.took.feature.auth.exception; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.exception.ErrorCode; -import com.evenly.took.global.exception.TookException; import lombok.Getter; diff --git a/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidRefreshTokenException.java b/src/main/java/com/evenly/took/feature/auth/exception/InvalidRefreshTokenException.java similarity index 68% rename from src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidRefreshTokenException.java rename to src/main/java/com/evenly/took/feature/auth/exception/InvalidRefreshTokenException.java index d72191e..d8d71a2 100644 --- a/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidRefreshTokenException.java +++ b/src/main/java/com/evenly/took/feature/auth/exception/InvalidRefreshTokenException.java @@ -1,7 +1,7 @@ -package com.evenly.took.global.exception.auth.oauth; +package com.evenly.took.feature.auth.exception; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.exception.ErrorCode; -import com.evenly.took.global.exception.TookException; import lombok.Getter; diff --git a/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidTokenException.java b/src/main/java/com/evenly/took/feature/auth/exception/InvalidTokenException.java similarity index 67% rename from src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidTokenException.java rename to src/main/java/com/evenly/took/feature/auth/exception/InvalidTokenException.java index fa6cb73..b3221bd 100644 --- a/src/main/java/com/evenly/took/global/exception/auth/oauth/InvalidTokenException.java +++ b/src/main/java/com/evenly/took/feature/auth/exception/InvalidTokenException.java @@ -1,7 +1,7 @@ -package com.evenly.took.global.exception.auth.oauth; +package com.evenly.took.feature.auth.exception; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.exception.ErrorCode; -import com.evenly.took.global.exception.TookException; import lombok.Getter; diff --git a/src/main/java/com/evenly/took/global/exception/auth/oauth/OAuthTypeNotFoundException.java b/src/main/java/com/evenly/took/feature/auth/exception/OAuthTypeNotFoundException.java similarity index 67% rename from src/main/java/com/evenly/took/global/exception/auth/oauth/OAuthTypeNotFoundException.java rename to src/main/java/com/evenly/took/feature/auth/exception/OAuthTypeNotFoundException.java index d700e78..fe51b6d 100644 --- a/src/main/java/com/evenly/took/global/exception/auth/oauth/OAuthTypeNotFoundException.java +++ b/src/main/java/com/evenly/took/feature/auth/exception/OAuthTypeNotFoundException.java @@ -1,7 +1,7 @@ -package com.evenly.took.global.exception.auth.oauth; +package com.evenly.took.feature.auth.exception; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.exception.ErrorCode; -import com.evenly.took.global.exception.TookException; import lombok.Getter; diff --git a/src/main/java/com/evenly/took/global/exception/CommonErrorCode.java b/src/main/java/com/evenly/took/feature/common/exception/CommonErrorCode.java similarity index 84% rename from src/main/java/com/evenly/took/global/exception/CommonErrorCode.java rename to src/main/java/com/evenly/took/feature/common/exception/CommonErrorCode.java index f3649b3..c8418a2 100644 --- a/src/main/java/com/evenly/took/global/exception/CommonErrorCode.java +++ b/src/main/java/com/evenly/took/feature/common/exception/CommonErrorCode.java @@ -1,7 +1,9 @@ -package com.evenly.took.global.exception; +package com.evenly.took.feature.common.exception; import org.springframework.http.HttpStatus; +import com.evenly.took.global.exception.ErrorCode; + import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/evenly/took/global/exception/TookException.java b/src/main/java/com/evenly/took/feature/common/exception/TookException.java similarity index 63% rename from src/main/java/com/evenly/took/global/exception/TookException.java rename to src/main/java/com/evenly/took/feature/common/exception/TookException.java index 223f0a9..ecad38e 100644 --- a/src/main/java/com/evenly/took/global/exception/TookException.java +++ b/src/main/java/com/evenly/took/feature/common/exception/TookException.java @@ -1,4 +1,6 @@ -package com.evenly.took.global.exception; +package com.evenly.took.feature.common.exception; + +import com.evenly.took.global.exception.ErrorCode; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/com/evenly/took/global/exception/GlobalExceptionHandler.java b/src/main/java/com/evenly/took/global/exception/GlobalExceptionHandler.java index 4a91754..544acbf 100644 --- a/src/main/java/com/evenly/took/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/evenly/took/global/exception/GlobalExceptionHandler.java @@ -5,6 +5,8 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.resource.NoResourceFoundException; +import com.evenly.took.feature.common.exception.CommonErrorCode; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.exception.dto.ErrorResponse; import com.evenly.took.global.exception.dto.ServerErrorResponse; import com.evenly.took.global.exception.dto.ValidationErrorResponse; diff --git a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java index fda9e45..c889396 100644 --- a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java @@ -10,9 +10,9 @@ import com.evenly.took.feature.auth.api.HeaderHandler; import com.evenly.took.feature.auth.application.TokenProvider; +import com.evenly.took.feature.auth.exception.AuthErrorCode; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.exception.ErrorCode; -import com.evenly.took.global.exception.TookException; -import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; import com.evenly.took.global.exception.dto.ErrorResponse; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; diff --git a/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java b/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java index 2063a92..885b144 100644 --- a/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java +++ b/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java @@ -6,9 +6,9 @@ import org.springframework.stereotype.Component; +import com.evenly.took.feature.auth.exception.AuthErrorCode; +import com.evenly.took.feature.auth.exception.InvalidAccessTokenException; import com.evenly.took.global.config.properties.jwt.AuthProperties; -import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; -import com.evenly.took.global.exception.auth.oauth.InvalidAccessTokenException; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; diff --git a/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java b/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java index 6aa5a6c..f5edd63 100644 --- a/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java +++ b/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java @@ -5,9 +5,9 @@ import org.springframework.stereotype.Component; +import com.evenly.took.feature.auth.exception.AuthErrorCode; +import com.evenly.took.feature.auth.exception.InvalidRefreshTokenException; import com.evenly.took.global.config.properties.jwt.AuthProperties; -import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; -import com.evenly.took.global.exception.auth.oauth.InvalidRefreshTokenException; import com.evenly.took.global.redis.RedisService; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java b/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java index 44b49f3..db5a53a 100644 --- a/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java +++ b/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java @@ -9,8 +9,8 @@ import org.springframework.stereotype.Component; import com.evenly.took.feature.auth.domain.OAuthType; -import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; -import com.evenly.took.global.exception.auth.oauth.OAuthTypeNotFoundException; +import com.evenly.took.feature.auth.exception.AuthErrorCode; +import com.evenly.took.feature.auth.exception.OAuthTypeNotFoundException; @Component public class AuthCodeRequestUrlProviderComposite { diff --git a/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java b/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java index 728422b..2f7e793 100644 --- a/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java +++ b/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java @@ -9,9 +9,9 @@ import org.springframework.stereotype.Component; import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.auth.exception.AuthErrorCode; +import com.evenly.took.feature.auth.exception.OAuthTypeNotFoundException; import com.evenly.took.feature.user.domain.User; -import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; -import com.evenly.took.global.exception.auth.oauth.OAuthTypeNotFoundException; @Component public class UserClientComposite { diff --git a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java index f05748e..d4bbc3a 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java @@ -5,7 +5,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import com.evenly.took.global.exception.auth.oauth.InvalidRefreshTokenException; +import com.evenly.took.feature.auth.exception.InvalidRefreshTokenException; import com.evenly.took.global.redis.RedisService; import com.evenly.took.global.security.auth.UuidTokenProvider; import com.evenly.took.global.service.ServiceTest; diff --git a/src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java b/src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java index 8588d36..3fe287b 100644 --- a/src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java +++ b/src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java @@ -11,8 +11,8 @@ import com.evenly.took.feature.auth.domain.OAuthIdentifier; import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.auth.exception.OAuthTypeNotFoundException; import com.evenly.took.feature.user.domain.User; -import com.evenly.took.global.exception.auth.oauth.OAuthTypeNotFoundException; import com.evenly.took.global.security.client.UserClient; import com.evenly.took.global.security.client.UserClientComposite; import com.evenly.took.global.service.MockTest; diff --git a/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java b/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java index 7139247..513abdc 100644 --- a/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java +++ b/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java @@ -10,8 +10,8 @@ import org.junit.jupiter.api.Test; import com.evenly.took.feature.auth.domain.OAuthType; -import com.evenly.took.global.exception.auth.jwt.AuthErrorCode; -import com.evenly.took.global.exception.auth.oauth.OAuthTypeNotFoundException; +import com.evenly.took.feature.auth.exception.AuthErrorCode; +import com.evenly.took.feature.auth.exception.OAuthTypeNotFoundException; import com.evenly.took.global.security.client.AuthCodeRequestUrlProvider; import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; import com.evenly.took.global.service.MockTest; diff --git a/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java index 9931b4e..656c68c 100644 --- a/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java @@ -6,9 +6,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.config.properties.jwt.AuthProperties; -import com.evenly.took.global.exception.TookException; import com.evenly.took.global.security.auth.JwtTokenProvider; import com.evenly.took.global.service.MockTest; From a451d3ef08cafa10116dc11ded834fd46d00290f Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 28 Feb 2025 22:05:14 +0900 Subject: [PATCH 26/30] =?UTF-8?q?refac:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존: 여러개의 커스텀 예외 사용 - 개선: 하나의 커스텀 예외 사용 --- .../took/feature/auth/api/HeaderHandler.java | 4 ++-- .../exception/InvalidAccessTokenException.java | 14 -------------- .../exception/InvalidRefreshTokenException.java | 14 -------------- .../auth/exception/InvalidTokenException.java | 14 -------------- .../auth/exception/OAuthTypeNotFoundException.java | 14 -------------- .../global/security/auth/JwtTokenProvider.java | 6 +++--- .../global/security/auth/UuidTokenProvider.java | 4 ++-- .../AuthCodeRequestUrlProviderComposite.java | 4 ++-- .../security/client/UserClientComposite.java | 4 ++-- .../auth/application/UuidTokenProviderTest.java | 6 +++--- .../auth/client/UserClientCompositeTest.java | 4 ++-- .../AuthCodeRequestUrlProviderCompositeTest.java | 4 ++-- 12 files changed, 18 insertions(+), 74 deletions(-) delete mode 100644 src/main/java/com/evenly/took/feature/auth/exception/InvalidAccessTokenException.java delete mode 100644 src/main/java/com/evenly/took/feature/auth/exception/InvalidRefreshTokenException.java delete mode 100644 src/main/java/com/evenly/took/feature/auth/exception/InvalidTokenException.java delete mode 100644 src/main/java/com/evenly/took/feature/auth/exception/OAuthTypeNotFoundException.java diff --git a/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java b/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java index 5888e9f..79e652f 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java +++ b/src/main/java/com/evenly/took/feature/auth/api/HeaderHandler.java @@ -3,7 +3,7 @@ import org.springframework.stereotype.Component; import com.evenly.took.feature.auth.exception.AuthErrorCode; -import com.evenly.took.feature.auth.exception.InvalidTokenException; +import com.evenly.took.feature.common.exception.TookException; import jakarta.servlet.http.HttpServletRequest; @@ -21,7 +21,7 @@ public String resolveAccessToken(HttpServletRequest request) { private void validateAuthHeader(String bearerToken) { if (bearerToken == null || !bearerToken.startsWith(HEADER_VALUE_PREFIX_OF_AUTH)) { - throw new InvalidTokenException(AuthErrorCode.JWT_UNAUTHORIZED); + throw new TookException(AuthErrorCode.JWT_UNAUTHORIZED); } } } diff --git a/src/main/java/com/evenly/took/feature/auth/exception/InvalidAccessTokenException.java b/src/main/java/com/evenly/took/feature/auth/exception/InvalidAccessTokenException.java deleted file mode 100644 index 9f5d992..0000000 --- a/src/main/java/com/evenly/took/feature/auth/exception/InvalidAccessTokenException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.evenly.took.feature.auth.exception; - -import com.evenly.took.feature.common.exception.TookException; -import com.evenly.took.global.exception.ErrorCode; - -import lombok.Getter; - -@Getter -public class InvalidAccessTokenException extends TookException { - - public InvalidAccessTokenException(final ErrorCode errorCode) { - super(errorCode); - } -} diff --git a/src/main/java/com/evenly/took/feature/auth/exception/InvalidRefreshTokenException.java b/src/main/java/com/evenly/took/feature/auth/exception/InvalidRefreshTokenException.java deleted file mode 100644 index d8d71a2..0000000 --- a/src/main/java/com/evenly/took/feature/auth/exception/InvalidRefreshTokenException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.evenly.took.feature.auth.exception; - -import com.evenly.took.feature.common.exception.TookException; -import com.evenly.took.global.exception.ErrorCode; - -import lombok.Getter; - -@Getter -public class InvalidRefreshTokenException extends TookException { - - public InvalidRefreshTokenException(final ErrorCode errorCode) { - super(errorCode); - } -} diff --git a/src/main/java/com/evenly/took/feature/auth/exception/InvalidTokenException.java b/src/main/java/com/evenly/took/feature/auth/exception/InvalidTokenException.java deleted file mode 100644 index b3221bd..0000000 --- a/src/main/java/com/evenly/took/feature/auth/exception/InvalidTokenException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.evenly.took.feature.auth.exception; - -import com.evenly.took.feature.common.exception.TookException; -import com.evenly.took.global.exception.ErrorCode; - -import lombok.Getter; - -@Getter -public class InvalidTokenException extends TookException { - - public InvalidTokenException(final ErrorCode errorCode) { - super(errorCode); - } -} diff --git a/src/main/java/com/evenly/took/feature/auth/exception/OAuthTypeNotFoundException.java b/src/main/java/com/evenly/took/feature/auth/exception/OAuthTypeNotFoundException.java deleted file mode 100644 index fe51b6d..0000000 --- a/src/main/java/com/evenly/took/feature/auth/exception/OAuthTypeNotFoundException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.evenly.took.feature.auth.exception; - -import com.evenly.took.feature.common.exception.TookException; -import com.evenly.took.global.exception.ErrorCode; - -import lombok.Getter; - -@Getter -public class OAuthTypeNotFoundException extends TookException { - - public OAuthTypeNotFoundException(ErrorCode errorCode) { - super(errorCode); - } -} diff --git a/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java b/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java index 885b144..b018630 100644 --- a/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java +++ b/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java @@ -7,7 +7,7 @@ import org.springframework.stereotype.Component; import com.evenly.took.feature.auth.exception.AuthErrorCode; -import com.evenly.took.feature.auth.exception.InvalidAccessTokenException; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.config.properties.jwt.AuthProperties; import io.jsonwebtoken.Claims; @@ -53,7 +53,7 @@ public void validateToken(String token) { parseClaims(token); } catch (JwtException | IllegalArgumentException e) { log.error(AuthErrorCode.JWT_UNAUTHORIZED.getMessage(), e); - throw new InvalidAccessTokenException(AuthErrorCode.JWT_UNAUTHORIZED); + throw new TookException(AuthErrorCode.JWT_UNAUTHORIZED); } } @@ -63,7 +63,7 @@ public String getUserId(String token) { .getBody() .getSubject(); } catch (JwtException ex) { - throw new InvalidAccessTokenException(AuthErrorCode.INVALID_ACCESS_TOKEN); + throw new TookException(AuthErrorCode.INVALID_ACCESS_TOKEN); } } diff --git a/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java b/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java index f5edd63..d07a587 100644 --- a/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java +++ b/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java @@ -6,7 +6,7 @@ import org.springframework.stereotype.Component; import com.evenly.took.feature.auth.exception.AuthErrorCode; -import com.evenly.took.feature.auth.exception.InvalidRefreshTokenException; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.config.properties.jwt.AuthProperties; import com.evenly.took.global.redis.RedisService; @@ -29,7 +29,7 @@ public String generateRefreshToken(String userId) { public String getUserId(String token) { Object userId = redisService.getValue(token); if (userId == null) { - throw new InvalidRefreshTokenException(AuthErrorCode.EXPIRED_REFRESH_TOKEN); + throw new TookException(AuthErrorCode.EXPIRED_REFRESH_TOKEN); } return userId.toString(); } diff --git a/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java b/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java index db5a53a..ea7c80d 100644 --- a/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java +++ b/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java @@ -10,7 +10,7 @@ import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.exception.AuthErrorCode; -import com.evenly.took.feature.auth.exception.OAuthTypeNotFoundException; +import com.evenly.took.feature.common.exception.TookException; @Component public class AuthCodeRequestUrlProviderComposite { @@ -24,7 +24,7 @@ public AuthCodeRequestUrlProviderComposite(Set provi public String provide(OAuthType oauthType) { return Optional.ofNullable(mapping.get(oauthType)) - .orElseThrow(() -> new OAuthTypeNotFoundException(AuthErrorCode.OAUTH_TYPE_NOT_FOUND)) + .orElseThrow(() -> new TookException(AuthErrorCode.OAUTH_TYPE_NOT_FOUND)) .provide(); } } diff --git a/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java b/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java index 2f7e793..8d34e84 100644 --- a/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java +++ b/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java @@ -10,7 +10,7 @@ import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.exception.AuthErrorCode; -import com.evenly.took.feature.auth.exception.OAuthTypeNotFoundException; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.feature.user.domain.User; @Component @@ -25,7 +25,7 @@ public UserClientComposite(Set clients) { public User fetch(OAuthType oauthType, String authCode) { return Optional.ofNullable(mapping.get(oauthType)) - .orElseThrow(() -> new OAuthTypeNotFoundException(AuthErrorCode.OAUTH_TYPE_NOT_FOUND)) + .orElseThrow(() -> new TookException(AuthErrorCode.OAUTH_TYPE_NOT_FOUND)) .fetch(authCode); } } diff --git a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java index d4bbc3a..4fb5022 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java @@ -5,7 +5,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import com.evenly.took.feature.auth.exception.InvalidRefreshTokenException; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.redis.RedisService; import com.evenly.took.global.security.auth.UuidTokenProvider; import com.evenly.took.global.service.ServiceTest; @@ -48,7 +48,7 @@ class UuidTokenProviderTest extends ServiceTest { @Test void 리프레쉬_토큰이_존재하지_않는_경우_예외를_반환한다() { assertThatThrownBy(() -> uuidTokenProvider.getUserId("dummy")) - .isInstanceOf(InvalidRefreshTokenException.class); + .isInstanceOf(TookException.class); } @Test @@ -59,6 +59,6 @@ class UuidTokenProviderTest extends ServiceTest { // when & then assertThatThrownBy(() -> uuidTokenProvider.getUserId(refreshToken + "invalid")) - .isInstanceOf(InvalidRefreshTokenException.class); + .isInstanceOf(TookException.class); } } diff --git a/src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java b/src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java index 3fe287b..7e632a3 100644 --- a/src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java +++ b/src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java @@ -11,7 +11,7 @@ import com.evenly.took.feature.auth.domain.OAuthIdentifier; import com.evenly.took.feature.auth.domain.OAuthType; -import com.evenly.took.feature.auth.exception.OAuthTypeNotFoundException; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.security.client.UserClient; import com.evenly.took.global.security.client.UserClientComposite; @@ -46,7 +46,7 @@ void setUp() { OAuthType invalidOAuthType = OAuthType.KAKAO; // when - OAuthTypeNotFoundException exception = assertThrows(OAuthTypeNotFoundException.class, () -> { + TookException exception = assertThrows(TookException.class, () -> { composite.fetch(invalidOAuthType, "testAuthCode"); }); diff --git a/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java b/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java index 513abdc..87dd608 100644 --- a/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java +++ b/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java @@ -11,7 +11,7 @@ import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.exception.AuthErrorCode; -import com.evenly.took.feature.auth.exception.OAuthTypeNotFoundException; +import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.security.client.AuthCodeRequestUrlProvider; import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; import com.evenly.took.global.service.MockTest; @@ -43,7 +43,7 @@ void setUp() { OAuthType invalidOAuthType = OAuthType.KAKAO; // when - OAuthTypeNotFoundException exception = assertThrows(OAuthTypeNotFoundException.class, () -> { + TookException exception = assertThrows(TookException.class, () -> { composite.provide(invalidOAuthType); }); From 51e56e36e29aec2d0df8fd8ba3487143018647ff Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 28 Feb 2025 22:18:44 +0900 Subject: [PATCH 27/30] =?UTF-8?q?refac:=20=EC=9D=B8=EC=A6=9D=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=ED=81=B4=EB=9E=98=EC=8A=A4=20auth=20feature=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/auth/application/AuthService.java | 4 ++-- .../auth/application}/JwtTokenProvider.java | 2 +- .../auth/application/TokenProvider.java | 2 -- .../auth/application}/UuidTokenProvider.java | 2 +- .../client/AuthCodeRequestUrlProvider.java | 2 +- .../AuthCodeRequestUrlProviderComposite.java | 2 +- .../auth}/client/UserClient.java | 2 +- .../auth}/client/UserClientComposite.java | 2 +- .../auth/AuthenticationFilter.java | 2 +- .../feature/auth/api/AuthIntegrationTest.java | 2 +- .../auth/application/AuthServiceTest.java | 2 +- .../JwtTokenProviderTest.java | 3 +-- .../UserClientCompositeTest.java | 6 ++--- .../application/UuidTokenProviderTest.java | 1 - ...thCodeRequestUrlProviderCompositeTest.java | 23 ++++++++----------- 15 files changed, 25 insertions(+), 32 deletions(-) rename src/main/java/com/evenly/took/{global/security/auth => feature/auth/application}/JwtTokenProvider.java (97%) rename src/main/java/com/evenly/took/{global/security/auth => feature/auth/application}/UuidTokenProvider.java (95%) rename src/main/java/com/evenly/took/{global/security => feature/auth}/client/AuthCodeRequestUrlProvider.java (75%) rename src/main/java/com/evenly/took/{global/security => feature/auth}/client/AuthCodeRequestUrlProviderComposite.java (95%) rename src/main/java/com/evenly/took/{global/security => feature/auth}/client/UserClient.java (80%) rename src/main/java/com/evenly/took/{global/security => feature/auth}/client/UserClientComposite.java (94%) rename src/main/java/com/evenly/took/global/{security => }/auth/AuthenticationFilter.java (98%) rename src/test/java/com/evenly/took/feature/auth/{jwt => application}/JwtTokenProviderTest.java (94%) rename src/test/java/com/evenly/took/feature/auth/{client => application}/UserClientCompositeTest.java (91%) rename src/test/java/com/evenly/took/feature/auth/client/{authcode => }/AuthCodeRequestUrlProviderCompositeTest.java (72%) diff --git a/src/main/java/com/evenly/took/feature/auth/application/AuthService.java b/src/main/java/com/evenly/took/feature/auth/application/AuthService.java index b1199cd..1b93233 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/AuthService.java +++ b/src/main/java/com/evenly/took/feature/auth/application/AuthService.java @@ -2,6 +2,8 @@ import org.springframework.stereotype.Service; +import com.evenly.took.feature.auth.client.AuthCodeRequestUrlProviderComposite; +import com.evenly.took.feature.auth.client.UserClientComposite; import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.dto.TokenDto; import com.evenly.took.feature.auth.dto.request.RefreshTokenRequest; @@ -10,8 +12,6 @@ import com.evenly.took.feature.auth.dto.response.TokenResponse; import com.evenly.took.feature.user.dao.UserRepository; import com.evenly.took.feature.user.domain.User; -import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; -import com.evenly.took.global.security.client.UserClientComposite; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/JwtTokenProvider.java similarity index 97% rename from src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java rename to src/main/java/com/evenly/took/feature/auth/application/JwtTokenProvider.java index b018630..07b3a67 100644 --- a/src/main/java/com/evenly/took/global/security/auth/JwtTokenProvider.java +++ b/src/main/java/com/evenly/took/feature/auth/application/JwtTokenProvider.java @@ -1,4 +1,4 @@ -package com.evenly.took.global.security.auth; +package com.evenly.took.feature.auth.application; import java.nio.charset.StandardCharsets; import java.security.Key; diff --git a/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java index e8e111a..6e73e61 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java +++ b/src/main/java/com/evenly/took/feature/auth/application/TokenProvider.java @@ -4,8 +4,6 @@ import com.evenly.took.feature.auth.dto.TokenDto; import com.evenly.took.feature.user.domain.User; -import com.evenly.took.global.security.auth.JwtTokenProvider; -import com.evenly.took.global.security.auth.UuidTokenProvider; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java similarity index 95% rename from src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java rename to src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java index d07a587..e44d3cd 100644 --- a/src/main/java/com/evenly/took/global/security/auth/UuidTokenProvider.java +++ b/src/main/java/com/evenly/took/feature/auth/application/UuidTokenProvider.java @@ -1,4 +1,4 @@ -package com.evenly.took.global.security.auth; +package com.evenly.took.feature.auth.application; import java.time.Duration; import java.util.UUID; diff --git a/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProvider.java b/src/main/java/com/evenly/took/feature/auth/client/AuthCodeRequestUrlProvider.java similarity index 75% rename from src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProvider.java rename to src/main/java/com/evenly/took/feature/auth/client/AuthCodeRequestUrlProvider.java index 7515c69..829207d 100644 --- a/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProvider.java +++ b/src/main/java/com/evenly/took/feature/auth/client/AuthCodeRequestUrlProvider.java @@ -1,4 +1,4 @@ -package com.evenly.took.global.security.client; +package com.evenly.took.feature.auth.client; import com.evenly.took.feature.auth.domain.OAuthType; diff --git a/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java b/src/main/java/com/evenly/took/feature/auth/client/AuthCodeRequestUrlProviderComposite.java similarity index 95% rename from src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java rename to src/main/java/com/evenly/took/feature/auth/client/AuthCodeRequestUrlProviderComposite.java index ea7c80d..d10a6ec 100644 --- a/src/main/java/com/evenly/took/global/security/client/AuthCodeRequestUrlProviderComposite.java +++ b/src/main/java/com/evenly/took/feature/auth/client/AuthCodeRequestUrlProviderComposite.java @@ -1,4 +1,4 @@ -package com.evenly.took.global.security.client; +package com.evenly.took.feature.auth.client; import java.util.Map; import java.util.Optional; diff --git a/src/main/java/com/evenly/took/global/security/client/UserClient.java b/src/main/java/com/evenly/took/feature/auth/client/UserClient.java similarity index 80% rename from src/main/java/com/evenly/took/global/security/client/UserClient.java rename to src/main/java/com/evenly/took/feature/auth/client/UserClient.java index 509bc45..803d76d 100644 --- a/src/main/java/com/evenly/took/global/security/client/UserClient.java +++ b/src/main/java/com/evenly/took/feature/auth/client/UserClient.java @@ -1,4 +1,4 @@ -package com.evenly.took.global.security.client; +package com.evenly.took.feature.auth.client; import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.user.domain.User; diff --git a/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java b/src/main/java/com/evenly/took/feature/auth/client/UserClientComposite.java similarity index 94% rename from src/main/java/com/evenly/took/global/security/client/UserClientComposite.java rename to src/main/java/com/evenly/took/feature/auth/client/UserClientComposite.java index 8d34e84..3756928 100644 --- a/src/main/java/com/evenly/took/global/security/client/UserClientComposite.java +++ b/src/main/java/com/evenly/took/feature/auth/client/UserClientComposite.java @@ -1,4 +1,4 @@ -package com.evenly.took.global.security.client; +package com.evenly.took.feature.auth.client; import java.util.Map; import java.util.Optional; diff --git a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java b/src/main/java/com/evenly/took/global/auth/AuthenticationFilter.java similarity index 98% rename from src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java rename to src/main/java/com/evenly/took/global/auth/AuthenticationFilter.java index c889396..930819a 100644 --- a/src/main/java/com/evenly/took/global/security/auth/AuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/auth/AuthenticationFilter.java @@ -1,4 +1,4 @@ -package com.evenly.took.global.security.auth; +package com.evenly.took.global.auth; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java b/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java index 145942f..0924ce3 100644 --- a/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java +++ b/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java @@ -7,13 +7,13 @@ import org.mockito.BDDMockito; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import com.evenly.took.feature.auth.client.UserClientComposite; import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.dto.request.RefreshTokenRequest; import com.evenly.took.feature.auth.dto.response.TokenResponse; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.domain.TestUserFactory; import com.evenly.took.global.integration.IntegrationTest; -import com.evenly.took.global.security.client.UserClientComposite; import io.restassured.http.ContentType; diff --git a/src/test/java/com/evenly/took/feature/auth/application/AuthServiceTest.java b/src/test/java/com/evenly/took/feature/auth/application/AuthServiceTest.java index 37c7239..f7c390e 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/AuthServiceTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/AuthServiceTest.java @@ -8,11 +8,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import com.evenly.took.feature.auth.client.UserClientComposite; import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.domain.TestUserFactory; -import com.evenly.took.global.security.client.UserClientComposite; import com.evenly.took.global.service.ServiceTest; class AuthServiceTest extends ServiceTest { diff --git a/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/JwtTokenProviderTest.java similarity index 94% rename from src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java rename to src/test/java/com/evenly/took/feature/auth/application/JwtTokenProviderTest.java index 656c68c..015ad24 100644 --- a/src/test/java/com/evenly/took/feature/auth/jwt/JwtTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/JwtTokenProviderTest.java @@ -1,4 +1,4 @@ -package com.evenly.took.feature.auth.jwt; +package com.evenly.took.feature.auth.application; import static com.evenly.took.global.domain.TestUserFactory.*; import static org.assertj.core.api.Assertions.*; @@ -9,7 +9,6 @@ import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.feature.user.domain.User; import com.evenly.took.global.config.properties.jwt.AuthProperties; -import com.evenly.took.global.security.auth.JwtTokenProvider; import com.evenly.took.global.service.MockTest; class JwtTokenProviderTest extends MockTest { diff --git a/src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java b/src/test/java/com/evenly/took/feature/auth/application/UserClientCompositeTest.java similarity index 91% rename from src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java rename to src/test/java/com/evenly/took/feature/auth/application/UserClientCompositeTest.java index 7e632a3..1652e93 100644 --- a/src/test/java/com/evenly/took/feature/auth/client/UserClientCompositeTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/UserClientCompositeTest.java @@ -1,4 +1,4 @@ -package com.evenly.took.feature.auth.client; +package com.evenly.took.feature.auth.application; import static com.evenly.took.global.domain.TestUserFactory.*; import static org.assertj.core.api.Assertions.*; @@ -9,12 +9,12 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.evenly.took.feature.auth.client.UserClient; +import com.evenly.took.feature.auth.client.UserClientComposite; import com.evenly.took.feature.auth.domain.OAuthIdentifier; import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.feature.user.domain.User; -import com.evenly.took.global.security.client.UserClient; -import com.evenly.took.global.security.client.UserClientComposite; import com.evenly.took.global.service.MockTest; class UserClientCompositeTest extends MockTest { diff --git a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java index 4fb5022..fc768aa 100644 --- a/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java +++ b/src/test/java/com/evenly/took/feature/auth/application/UuidTokenProviderTest.java @@ -7,7 +7,6 @@ import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.redis.RedisService; -import com.evenly.took.global.security.auth.UuidTokenProvider; import com.evenly.took.global.service.ServiceTest; class UuidTokenProviderTest extends ServiceTest { diff --git a/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java b/src/test/java/com/evenly/took/feature/auth/client/AuthCodeRequestUrlProviderCompositeTest.java similarity index 72% rename from src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java rename to src/test/java/com/evenly/took/feature/auth/client/AuthCodeRequestUrlProviderCompositeTest.java index 87dd608..a88eefe 100644 --- a/src/test/java/com/evenly/took/feature/auth/client/authcode/AuthCodeRequestUrlProviderCompositeTest.java +++ b/src/test/java/com/evenly/took/feature/auth/client/AuthCodeRequestUrlProviderCompositeTest.java @@ -1,6 +1,5 @@ -package com.evenly.took.feature.auth.client.authcode; +package com.evenly.took.feature.auth.client; -import static com.evenly.took.feature.auth.client.authcode.AuthCodeRequestUrlProviderCompositeTest.*; import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; @@ -12,8 +11,6 @@ import com.evenly.took.feature.auth.domain.OAuthType; import com.evenly.took.feature.auth.exception.AuthErrorCode; import com.evenly.took.feature.common.exception.TookException; -import com.evenly.took.global.security.client.AuthCodeRequestUrlProvider; -import com.evenly.took.global.security.client.AuthCodeRequestUrlProviderComposite; import com.evenly.took.global.service.MockTest; class AuthCodeRequestUrlProviderCompositeTest extends MockTest { @@ -50,17 +47,17 @@ void setUp() { // then assertThat(exception.getErrorCode()).isEqualTo(AuthErrorCode.OAUTH_TYPE_NOT_FOUND); } -} -class MockGoogleAuthCodeRequestUrlProvider implements AuthCodeRequestUrlProvider { + static class MockGoogleAuthCodeRequestUrlProvider implements AuthCodeRequestUrlProvider { - @Override - public OAuthType supportType() { - return OAuthType.GOOGLE; - } + @Override + public OAuthType supportType() { + return OAuthType.GOOGLE; + } - @Override - public String provide() { - return TEST_URL; + @Override + public String provide() { + return TEST_URL; + } } } From 196cf6353ee66568d988e9e9eed468c4fdf6301e Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 28 Feb 2025 22:41:58 +0900 Subject: [PATCH 28/30] =?UTF-8?q?docs:=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../evenly/took/feature/auth/api/AuthApi.java | 32 +++++++++++++------ .../took/feature/auth/api/AuthController.java | 3 +- .../feature/auth/api/AuthIntegrationTest.java | 4 +-- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/auth/api/AuthApi.java b/src/main/java/com/evenly/took/feature/auth/api/AuthApi.java index 89eab1c..c99cb95 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/AuthApi.java +++ b/src/main/java/com/evenly/took/feature/auth/api/AuthApi.java @@ -2,18 +2,24 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import com.evenly.took.feature.auth.domain.OAuthType; +import com.evenly.took.feature.auth.dto.request.RefreshTokenRequest; import com.evenly.took.feature.auth.dto.response.AuthResponse; import com.evenly.took.feature.auth.dto.response.OAuthUrlResponse; +import com.evenly.took.feature.auth.dto.response.TokenResponse; +import com.evenly.took.global.exception.dto.ErrorResponse; import com.evenly.took.global.response.SuccessResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; @Tag(name = "[1. Auth]") @@ -22,10 +28,9 @@ public interface AuthApi { @Operation( summary = "소셜 로그인 인가 URL 리다이렉트", description = "지정된 OAuthType에 따른 소셜 로그인 인가 코드 요청 URL로 클라이언트를 리다이렉트합니다.") - @ApiResponse( - responseCode = "302", - description = "리다이렉트 성공", - content = @Content(schema = @Schema(implementation = SuccessResponse.class))) + @ApiResponses({ + @ApiResponse(responseCode = "302", description = "리다이렉트 성공") + }) @GetMapping("/api/auth/{oauthType}") SuccessResponse redirectAuthRequestUrl( @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @@ -34,10 +39,9 @@ SuccessResponse redirectAuthRequestUrl( @Operation( summary = "소셜 로그인 및 토큰 발급", description = "소셜 로그인 인가 코드를 통해 토큰(Access Token & Refresh Token)을 발급받습니다.") - @ApiResponse( - responseCode = "200", - description = "로그인 성공", - content = @Content(schema = @Schema(implementation = SuccessResponse.class))) + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "로그인 성공") + }) @GetMapping("/api/auth/login/{oauthType}") SuccessResponse login( // TODO 에러 응답 추가 @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @@ -45,5 +49,15 @@ SuccessResponse login( // TODO 에러 응답 추가 @Parameter(description = "소셜 서버로부터 전달받은 인가 코드", required = true) @RequestParam String code); - // TODO refresh API 추가 + @Operation( + summary = "토큰 재발급", + description = "토큰(Access Token)을 재발급받습니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "토큰 재발급 성공"), + @ApiResponse(responseCode = "401", description = "Refresh Token 만료", content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + @PostMapping("/api/auth/refresh") + SuccessResponse refreshToken( + @RequestBody(description = "Access Token을 재발급 받기 위한 Refresh Token", required = true) + @org.springframework.web.bind.annotation.RequestBody RefreshTokenRequest request); } diff --git a/src/main/java/com/evenly/took/feature/auth/api/AuthController.java b/src/main/java/com/evenly/took/feature/auth/api/AuthController.java index 983adb1..e8ceef1 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/AuthController.java +++ b/src/main/java/com/evenly/took/feature/auth/api/AuthController.java @@ -3,6 +3,7 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -35,7 +36,7 @@ public SuccessResponse login(@PathVariable OAuthType oauthType, @R return SuccessResponse.of(response); } - @GetMapping("/api/auth/refresh") + @PostMapping("/api/auth/refresh") public SuccessResponse refreshToken(@RequestBody RefreshTokenRequest request) { TokenResponse response = authService.refreshToken(request); return SuccessResponse.of(response); diff --git a/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java b/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java index 0924ce3..9159c4b 100644 --- a/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java +++ b/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java @@ -66,7 +66,7 @@ public class AuthIntegrationTest extends IntegrationTest { given().log().all() .contentType(ContentType.JSON) .body(request) - .when().get("/api/auth/refresh") + .when().post("/api/auth/refresh") .then().log().all() .statusCode(200); } @@ -81,7 +81,7 @@ public class AuthIntegrationTest extends IntegrationTest { given().log().all() .contentType(ContentType.JSON) .body(request) - .when().get("/api/auth/refresh") + .when().post("/api/auth/refresh") .then().log().all() .statusCode(401); } From 284fc05699e79b34a23b97cee971984c9bd96ddf Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 28 Feb 2025 22:50:34 +0900 Subject: [PATCH 29/30] =?UTF-8?q?refac:=20=EC=9D=B8=EC=A6=9D=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=EC=97=90=EC=84=9C=20=EC=83=81=ED=99=A9=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EC=98=88=EC=99=B8=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../took/feature/auth/application/JwtTokenProvider.java | 4 ++-- .../com/evenly/took/feature/auth/exception/AuthErrorCode.java | 1 - .../com/evenly/took/global/auth/AuthenticationFilter.java | 4 +--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/auth/application/JwtTokenProvider.java b/src/main/java/com/evenly/took/feature/auth/application/JwtTokenProvider.java index 07b3a67..e84ce8b 100644 --- a/src/main/java/com/evenly/took/feature/auth/application/JwtTokenProvider.java +++ b/src/main/java/com/evenly/took/feature/auth/application/JwtTokenProvider.java @@ -52,8 +52,8 @@ public void validateToken(String token) { try { parseClaims(token); } catch (JwtException | IllegalArgumentException e) { - log.error(AuthErrorCode.JWT_UNAUTHORIZED.getMessage(), e); - throw new TookException(AuthErrorCode.JWT_UNAUTHORIZED); + log.error(AuthErrorCode.INVALID_ACCESS_TOKEN.getMessage(), e); + throw new TookException(AuthErrorCode.INVALID_ACCESS_TOKEN); } } diff --git a/src/main/java/com/evenly/took/feature/auth/exception/AuthErrorCode.java b/src/main/java/com/evenly/took/feature/auth/exception/AuthErrorCode.java index 8e5f358..46cae84 100644 --- a/src/main/java/com/evenly/took/feature/auth/exception/AuthErrorCode.java +++ b/src/main/java/com/evenly/took/feature/auth/exception/AuthErrorCode.java @@ -14,7 +14,6 @@ public enum AuthErrorCode implements ErrorCode { OAUTH_TYPE_NOT_FOUND(HttpStatus.NOT_FOUND, "OAuth 타입을 찾을 수 없습니다."), JWT_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "JWT를 찾을 수 없습니다."), EXPIRED_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "refresh token이 만료되었습니다."), - EXPIRED_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, "access token이 만료되었습니다."), INVALID_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, "access token이 유효하지 않습니다."), ; diff --git a/src/main/java/com/evenly/took/global/auth/AuthenticationFilter.java b/src/main/java/com/evenly/took/global/auth/AuthenticationFilter.java index 930819a..d1bec58 100644 --- a/src/main/java/com/evenly/took/global/auth/AuthenticationFilter.java +++ b/src/main/java/com/evenly/took/global/auth/AuthenticationFilter.java @@ -10,7 +10,6 @@ import com.evenly.took.feature.auth.api.HeaderHandler; import com.evenly.took.feature.auth.application.TokenProvider; -import com.evenly.took.feature.auth.exception.AuthErrorCode; import com.evenly.took.feature.common.exception.TookException; import com.evenly.took.global.exception.ErrorCode; import com.evenly.took.global.exception.dto.ErrorResponse; @@ -58,8 +57,7 @@ protected void doFilterInternal( checkTokens(request); filterChain.doFilter(request, response); } catch (TookException ex) { - AuthErrorCode errorCode = AuthErrorCode.EXPIRED_ACCESS_TOKEN; - sendError(response, errorCode); + sendError(response, ex.getErrorCode()); } } From dd082d476e4ee61dbeb4da9e02ca52fbb8123890 Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 28 Feb 2025 22:54:16 +0900 Subject: [PATCH 30/30] refac: login API HTTP method GET -> POST --- src/main/java/com/evenly/took/feature/auth/api/AuthApi.java | 2 +- .../com/evenly/took/feature/auth/api/AuthController.java | 2 +- .../evenly/took/feature/auth/api/AuthIntegrationTest.java | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/evenly/took/feature/auth/api/AuthApi.java b/src/main/java/com/evenly/took/feature/auth/api/AuthApi.java index c99cb95..64275d1 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/AuthApi.java +++ b/src/main/java/com/evenly/took/feature/auth/api/AuthApi.java @@ -42,7 +42,7 @@ SuccessResponse redirectAuthRequestUrl( @ApiResponses({ @ApiResponse(responseCode = "200", description = "로그인 성공") }) - @GetMapping("/api/auth/login/{oauthType}") + @PostMapping("/api/auth/login/{oauthType}") SuccessResponse login( // TODO 에러 응답 추가 @Parameter(description = "소셜 공급자 타입 (예: GOOGLE, KAKAO, APPLE)", required = true, example = "GOOGLE") @PathVariable OAuthType oauthType, diff --git a/src/main/java/com/evenly/took/feature/auth/api/AuthController.java b/src/main/java/com/evenly/took/feature/auth/api/AuthController.java index e8ceef1..52a8f29 100644 --- a/src/main/java/com/evenly/took/feature/auth/api/AuthController.java +++ b/src/main/java/com/evenly/took/feature/auth/api/AuthController.java @@ -30,7 +30,7 @@ public SuccessResponse redirectAuthRequestUrl(@PathVariable OA return SuccessResponse.of(HttpStatus.FOUND, response); } - @GetMapping("/api/auth/login/{oauthType}") + @PostMapping("/api/auth/login/{oauthType}") public SuccessResponse login(@PathVariable OAuthType oauthType, @RequestParam String code) { AuthResponse response = authService.loginAndGenerateToken(oauthType, code); return SuccessResponse.of(response); diff --git a/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java b/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java index 9159c4b..2162cd8 100644 --- a/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java +++ b/src/test/java/com/evenly/took/feature/auth/api/AuthIntegrationTest.java @@ -29,7 +29,7 @@ public class AuthIntegrationTest extends IntegrationTest { .willReturn(user); given().log().all() - .when().get("/api/auth/login/KAKAO?code=code") + .when().post("/api/auth/login/KAKAO?code=code") .then().log().all() .statusCode(200); } @@ -54,7 +54,7 @@ public class AuthIntegrationTest extends IntegrationTest { .willReturn(user); TokenResponse tokens = given().log().all() - .when().get("/api/auth/login/KAKAO?code=code") + .when().post("/api/auth/login/KAKAO?code=code") .then().log().all() .statusCode(200) .extract() @@ -93,7 +93,7 @@ public class AuthIntegrationTest extends IntegrationTest { .willReturn(user); TokenResponse tokens = given().log().all() - .when().get("/api/auth/login/KAKAO?code=code") + .when().post("/api/auth/login/KAKAO?code=code") .then().log().all() .statusCode(200) .extract()