From 80f78de86386e39f7dd8f909d3f792aaabedb469 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 3 Jan 2025 17:20:01 +0900 Subject: [PATCH 1/7] =?UTF-8?q?fix:=20import=EB=AC=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/spot/spotserver/api/auth/jwt/redis/Token.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/spot/spotserver/api/auth/jwt/redis/Token.java b/src/main/java/com/spot/spotserver/api/auth/jwt/redis/Token.java index 7c784bb..f20c956 100644 --- a/src/main/java/com/spot/spotserver/api/auth/jwt/redis/Token.java +++ b/src/main/java/com/spot/spotserver/api/auth/jwt/redis/Token.java @@ -1,12 +1,12 @@ package com.spot.spotserver.api.auth.jwt.redis; -import jakarta.persistence.Id; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import org.springframework.data.annotation.Id; import org.springframework.data.redis.core.RedisHash; -@RedisHash(value = "Token", timeToLive = 60 * 60 * 24 * 14) +@RedisHash(value = "refreshToken", timeToLive = 60 * 60 * 24 * 14) @AllArgsConstructor @Getter @Builder @@ -18,11 +18,11 @@ public class Token { private String refreshToken; public static Token of( - final Long id, + final Long userId, final String refreshToken ) { return Token.builder() - .id(id.toString()) + .id(userId.toString()) .refreshToken(refreshToken) .build(); } From 16f192cac2bb216a97c5f05bcf67612c3058ed58 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 3 Jan 2025 17:21:05 +0900 Subject: [PATCH 2/7] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20import=EB=AC=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/spot/spotserver/api/auth/jwt/redis/TokenRepository.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/spot/spotserver/api/auth/jwt/redis/TokenRepository.java b/src/main/java/com/spot/spotserver/api/auth/jwt/redis/TokenRepository.java index a3a561b..563c301 100644 --- a/src/main/java/com/spot/spotserver/api/auth/jwt/redis/TokenRepository.java +++ b/src/main/java/com/spot/spotserver/api/auth/jwt/redis/TokenRepository.java @@ -2,7 +2,5 @@ import org.springframework.data.repository.CrudRepository; -import java.util.Optional; - public interface TokenRepository extends CrudRepository { } From e46cfa443f1e41fad0ca09cd430d7625f42f51cf Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 3 Jan 2025 17:22:04 +0900 Subject: [PATCH 3/7] =?UTF-8?q?chore:=20=EC=95=A1=EC=84=B8=EC=8A=A4=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EB=A7=8C=EB=A3=8C=20=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/spot/spotserver/api/auth/jwt/JwtTokenProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/spot/spotserver/api/auth/jwt/JwtTokenProvider.java b/src/main/java/com/spot/spotserver/api/auth/jwt/JwtTokenProvider.java index 64364ed..801abe3 100644 --- a/src/main/java/com/spot/spotserver/api/auth/jwt/JwtTokenProvider.java +++ b/src/main/java/com/spot/spotserver/api/auth/jwt/JwtTokenProvider.java @@ -23,7 +23,7 @@ public class JwtTokenProvider { private static final String USER_ID = "userId"; - private static final Long ACCESS_TOKEN_EXPIRATION_TIME = 60 * 60 * 1000L * 24; // 1일 + private static final Long ACCESS_TOKEN_EXPIRATION_TIME = 60 * 60 * 1000L * 5; // 5시간 private static final Long REFRESH_TOKEN_EXPIRATION_TIME = 60 * 60 * 1000L * 24 * 14; // 14일 @Value("${jwt.secret}") From 0f6249829c35bfc47055013182f4afd16c4256aa Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 3 Jan 2025 17:23:15 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20RefreshTokenService=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=20=EC=A1=B0=ED=9A=8C=20=EB=A9=94=EC=86=8C=EB=93=9C=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 --- .../api/auth/jwt/redis/RefreshTokenService.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/spot/spotserver/api/auth/jwt/redis/RefreshTokenService.java b/src/main/java/com/spot/spotserver/api/auth/jwt/redis/RefreshTokenService.java index f8602bc..8b4e53c 100644 --- a/src/main/java/com/spot/spotserver/api/auth/jwt/redis/RefreshTokenService.java +++ b/src/main/java/com/spot/spotserver/api/auth/jwt/redis/RefreshTokenService.java @@ -12,12 +12,19 @@ public class RefreshTokenService { @Transactional public void saveRefreshToken(final Long userId, final String refreshToken) { - // 기존 리프레시 토큰 삭제 - deleteRefreshToken(userId); - // 새로운 리프레시 토큰 저장 + String strUserId = userId.toString(); + if (tokenRepository.existsById(strUserId)) { + tokenRepository.deleteById(strUserId); + } tokenRepository.save(Token.of(userId, refreshToken)); } + public String getRefreshToken(final Long userId) { + return tokenRepository.findById(userId.toString()) + .map(Token::getRefreshToken) + .orElse(null); + } + public void deleteRefreshToken(final Long userId) { String strUserId = userId.toString(); if (tokenRepository.existsById(strUserId)) { From 2632124b28789d5f44c4a230c47bf2ae6c6eb3d4 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 3 Jan 2025 17:24:04 +0900 Subject: [PATCH 5/7] =?UTF-8?q?refac:=20AuthService=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EB=B0=8F=20=ED=86=A0=ED=81=B0=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=A1=9C=EC=A7=81=EB=A7=8C=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/auth/service/AuthService.java | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/spot/spotserver/api/auth/service/AuthService.java b/src/main/java/com/spot/spotserver/api/auth/service/AuthService.java index 5560a86..81722d6 100644 --- a/src/main/java/com/spot/spotserver/api/auth/service/AuthService.java +++ b/src/main/java/com/spot/spotserver/api/auth/service/AuthService.java @@ -1,20 +1,19 @@ package com.spot.spotserver.api.auth.service; import com.spot.spotserver.api.auth.client.KakaoApiClient; -import com.spot.spotserver.api.auth.client.KakaoAuthApiClient; -import com.spot.spotserver.api.auth.dto.response.KakaoAccessTokenResponse; import com.spot.spotserver.api.auth.dto.response.KakaoUserResponse; import com.spot.spotserver.api.auth.dto.response.TokenResponse; +import com.spot.spotserver.api.auth.exception.JwtCustomException; import com.spot.spotserver.api.auth.exception.OAuth2TokenException; import com.spot.spotserver.api.auth.handler.UserAuthentication; import com.spot.spotserver.api.auth.jwt.JwtTokenProvider; +import com.spot.spotserver.api.auth.jwt.JwtValidationType; import com.spot.spotserver.api.auth.jwt.redis.RefreshTokenService; import com.spot.spotserver.api.user.domain.User; import com.spot.spotserver.api.user.exception.UserNotFoundException; import com.spot.spotserver.api.user.repository.UserRepository; import com.spot.spotserver.api.user.service.UserService; import com.spot.spotserver.common.payload.ErrorCode; -import feign.FeignException; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; @@ -24,17 +23,10 @@ @RequiredArgsConstructor public class AuthService { - private static final String AUTH_CODE = "authorization_code"; - private static final String REDIRECT_URI = "http://localhost:8080/api/login/kakao"; - @Value("${spring.security.oauth2.client.registration.kakao.client-id}") private String clientId; - @Value("${spring.security.oauth2.client.registration.kakao.client-secret}") - private String clientSecret; - private final KakaoApiClient kakaoApiClient; - private final KakaoAuthApiClient kakaoAuthApiClient; private final JwtTokenProvider jwtTokenProvider; private final UserService userService; private final UserRepository userRepository; @@ -47,39 +39,48 @@ public TokenResponse login(final String accessToken) { } // 카카오 액세스 토큰으로 사용자 정보 가져오기 - KakaoUserResponse userResponse; - try { - userResponse = getUserInfo(accessToken); - } catch (FeignException e) { - throw new OAuth2TokenException(ErrorCode.USER_INFO_REQUEST_FAILED); - } + KakaoUserResponse userResponse = getUserInfo(accessToken); + Long userId = userService.processUser(userResponse); + + // 기존 리프레시 토큰 확인 및 재사용 + String existingRefreshToken = refreshTokenService.getRefreshToken(userId); + String jwtRefreshToken = existingRefreshToken != null + ? existingRefreshToken + : jwtTokenProvider.issueRefreshToken(new UserAuthentication(userId, null, null)); - // 서비스 자체 JWT 액세스 및 리프레시 토큰 생성 - UserAuthentication authentication = new UserAuthentication(userResponse.id(), null, null); - String jwtAccessToken = jwtTokenProvider.issueAccessToken(authentication); - String jwtRefreshToken = jwtTokenProvider.issueRefreshToken(authentication); + // Redis에 리프레시 토큰 저장 + refreshTokenService.saveRefreshToken(userService.getIdBySocialId(userResponse.id()), jwtRefreshToken); - // 리프레시 토큰 레디스에 저장 - refreshTokenService.saveRefreshToken(userResponse.id(), jwtRefreshToken); + // 액세스 토큰 생성 + String jwtAccessToken = jwtTokenProvider.issueAccessToken(new UserAuthentication(userId, null, null)); - return processUser(userResponse); + return TokenResponse.of(jwtAccessToken, jwtRefreshToken); } private KakaoUserResponse getUserInfo(final String accessToken) { return kakaoApiClient.getUserInformation("Bearer " + accessToken); } - private TokenResponse processUser(KakaoUserResponse userResponse) { - if (userService.isExistingUser(userResponse.id())) { - return userService.getTokenByUserId(userService.getIdBySocialId(userResponse.id())); - } else { - return userService.getTokenByUserId(userService.createUser(userResponse)); - } - } - public User getUserFromAccessToken(String accessToken) { Long userId = jwtTokenProvider.getUserFromJwt(accessToken); return userRepository.findById(userId) .orElseThrow(() -> new UserNotFoundException(ErrorCode.USER_NOT_FOUND)); } + + public TokenResponse reissueToken(final String refreshToken) { + JwtValidationType validationType = jwtTokenProvider.validateToken(refreshToken); + + if (validationType != JwtValidationType.VALID_JWT) { + throw new JwtCustomException(ErrorCode.INVALID_JWT_TOKEN); + } + + Long userId = jwtTokenProvider.getUserFromJwt(refreshToken); + UserAuthentication userAuthentication = new UserAuthentication(userId, null, null); + String newAccessToken = jwtTokenProvider.issueAccessToken(userAuthentication); + String newRefreshToken = jwtTokenProvider.issueRefreshToken(userAuthentication); + + // 새로운 리프레시 토큰으로 교체 + refreshTokenService.saveRefreshToken(userId, newRefreshToken); + return TokenResponse.of(newAccessToken, newRefreshToken); + } } From 2a59792f952646f801a4e8365ce5afb122cb9298 Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 3 Jan 2025 17:24:35 +0900 Subject: [PATCH 6/7] =?UTF-8?q?refac:=20UserService=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=EA=B4=80=EB=A0=A8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=EB=A7=8C=20=EC=B2=98=EB=A6=AC=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/user/service/UserService.java | 48 +++++-------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/spot/spotserver/api/user/service/UserService.java b/src/main/java/com/spot/spotserver/api/user/service/UserService.java index db4c1c7..8f4f64b 100644 --- a/src/main/java/com/spot/spotserver/api/user/service/UserService.java +++ b/src/main/java/com/spot/spotserver/api/user/service/UserService.java @@ -2,12 +2,6 @@ import com.spot.spotserver.api.auth.client.KakaoAccount; import com.spot.spotserver.api.auth.dto.response.KakaoUserResponse; -import com.spot.spotserver.api.auth.dto.response.TokenResponse; -import com.spot.spotserver.api.auth.exception.JwtCustomException; -import com.spot.spotserver.api.auth.handler.UserAuthentication; -import com.spot.spotserver.api.auth.jwt.JwtTokenProvider; -import com.spot.spotserver.api.auth.jwt.JwtValidationType; -import com.spot.spotserver.api.auth.jwt.redis.RefreshTokenService; import com.spot.spotserver.api.badge.domain.Badge; import com.spot.spotserver.api.quiz.dto.UserBadgeResponse; import com.spot.spotserver.api.badge.repository.BadgeRepository; @@ -37,13 +31,19 @@ @RequiredArgsConstructor public class UserService { - private final JwtTokenProvider jwtTokenProvider; private final UserRepository userRepository; private final LikesRepository likesRepository; private final BadgeRepository badgeRepository; - private final RefreshTokenService refreshTokenService; private final S3Service s3Service; + public Long processUser(final KakaoUserResponse userResponse) { + if (isExistingUser(userResponse.id())) { + return getIdBySocialId(userResponse.id()); + } else { + return createUser(userResponse); + } + } + public Long createUser(final KakaoUserResponse userResponse) { String email = Optional.ofNullable(userResponse.kakaoAccount()) .map(KakaoAccount::email) @@ -53,41 +53,15 @@ public Long createUser(final KakaoUserResponse userResponse) { } public Long getIdBySocialId(final Long socialId) { - User user = userRepository.findBySocialId(socialId) - .orElseThrow(() -> new UserNotFoundException(ErrorCode.USER_NOT_FOUND)); - return user.getId(); + return userRepository.findBySocialId(socialId) + .orElseThrow(() -> new UserNotFoundException(ErrorCode.USER_NOT_FOUND)) + .getId(); } public boolean isExistingUser(final Long socialId) { return userRepository.findBySocialId(socialId).isPresent(); } - public TokenResponse getTokenByUserId(final Long id) { - UserAuthentication userAuthentication = new UserAuthentication(id, null, null); - String refreshToken = jwtTokenProvider.issueRefreshToken(userAuthentication); - refreshTokenService.saveRefreshToken(id, refreshToken); - return TokenResponse.of( - jwtTokenProvider.issueAccessToken(userAuthentication), - refreshToken - ); - } - - public TokenResponse reissueToken(final String refreshToken) { - JwtValidationType validationType = jwtTokenProvider.validateToken(refreshToken); - if (validationType != JwtValidationType.VALID_JWT) { - throw new JwtCustomException(ErrorCode.INVALID_JWT_TOKEN); - } - - Long userId = jwtTokenProvider.getUserFromJwt(refreshToken); - UserAuthentication userAuthentication = new UserAuthentication(userId, null, null); - String newAccessToken = jwtTokenProvider.issueAccessToken(userAuthentication); - String newRefreshToken = jwtTokenProvider.issueRefreshToken(userAuthentication); - - // 새로운 리프레시 토큰으로 교체 - refreshTokenService.saveRefreshToken(userId, newRefreshToken); - return TokenResponse.of(newAccessToken, newRefreshToken); - } - public String saveNickname(NicknameRequest nicknameRequest, User user) { userRepository.findById(user.getId()) .orElseThrow(() -> new UserNotFoundException(ErrorCode.USER_NOT_FOUND)); From 2fc0bccddd0cdd3cf815296b4c47582c9110352f Mon Sep 17 00:00:00 2001 From: Jeongmin39 Date: Fri, 3 Jan 2025 17:26:35 +0900 Subject: [PATCH 7/7] =?UTF-8?q?refac:=20Service=EB=8B=A8=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spotserver/api/auth/controller/AuthController.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/spot/spotserver/api/auth/controller/AuthController.java b/src/main/java/com/spot/spotserver/api/auth/controller/AuthController.java index 963a9f5..d07c3e1 100644 --- a/src/main/java/com/spot/spotserver/api/auth/controller/AuthController.java +++ b/src/main/java/com/spot/spotserver/api/auth/controller/AuthController.java @@ -3,21 +3,16 @@ import com.spot.spotserver.api.auth.dto.request.TokenRequest; import com.spot.spotserver.api.auth.dto.response.TokenResponse; import com.spot.spotserver.api.auth.service.AuthService; -import com.spot.spotserver.api.user.service.UserService; import com.spot.spotserver.common.payload.ApiResponse; import com.spot.spotserver.common.payload.SuccessCode; import lombok.RequiredArgsConstructor; -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; +import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor public class AuthController { private final AuthService authService; - private final UserService userService; @PostMapping("/api/login/kakao") public ApiResponse login(@RequestParam final String accessToken) { @@ -34,7 +29,7 @@ public ApiResponse login(@RequestParam final String accessToken) @PostMapping("/api/refresh") public ApiResponse reissueToken(@RequestBody TokenRequest request) { - TokenResponse result = userService.reissueToken(request.refreshToken()); + TokenResponse result = authService.reissueToken(request.refreshToken()); return ApiResponse.success(SuccessCode.REISSUE_TOKEN_SUCCESS, result); } }