11package com .pinback .application .auth .usecase ;
22
33import java .time .LocalTime ;
4+ import java .util .UUID ;
45
6+ import org .springframework .beans .factory .annotation .Value ;
7+ import org .springframework .data .redis .core .StringRedisTemplate ;
58import org .springframework .stereotype .Service ;
69import org .springframework .transaction .annotation .Transactional ;
710
811import com .pinback .application .auth .dto .SignUpCommand ;
912import com .pinback .application .auth .dto .SignUpCommandV3 ;
1013import com .pinback .application .auth .dto .SignUpResponse ;
14+ import com .pinback .application .auth .dto .SignUpResponseV3 ;
1115import com .pinback .application .auth .dto .TokenResponse ;
1216import com .pinback .application .auth .service .JwtProvider ;
17+ import com .pinback .application .common .exception .InvalidTokenException ;
1318import com .pinback .application .config .ProfileImageConfig ;
1419import com .pinback .application .google .dto .response .GoogleLoginResponse ;
1520import com .pinback .application .google .dto .response .GoogleLoginResponseV3 ;
3035@ Service
3136@ RequiredArgsConstructor
3237public class AuthUsecase {
38+ private static final String REDIS_REFRESH_TOKEN_PREFIX = "RT:" ;
3339
3440 private final UserValidateServicePort userValidateServicePort ;
3541 private final UserSaveServicePort userSaveServicePort ;
@@ -40,6 +46,10 @@ public class AuthUsecase {
4046 private final UserUpdateServicePort userUpdateServicePort ;
4147 private final UserOAuthUsecase userOAuthUsecase ;
4248 private final ProfileImageConfig profileImageConfig ;
49+ private final StringRedisTemplate stringRedisTemplate ;
50+
51+ @ Value ("${jwt.refreshExpirationPeriod}" )
52+ private long refreshTokenExpirationPeriod ;
4353
4454 @ Transactional
4555 public SignUpResponse signUp (SignUpCommand signUpCommand ) {
@@ -123,9 +133,11 @@ public SignUpResponse signUpV2(SignUpCommand signUpCommand) {
123133 }
124134
125135 @ Transactional
126- public SignUpResponse signUpV3 (SignUpCommandV3 signUpCommand ) {
136+ public SignUpResponseV3 signUpV3 (SignUpCommandV3 signUpCommand ) {
127137 User user = userGetServicePort .findByEmail (signUpCommand .email ());
128138 String accessToken = jwtProvider .createAccessToken (user .getId ());
139+ String refreshToken = jwtProvider .createRefreshToken (user .getId ());
140+ saveRefreshTokenToRedis (user .getId (), refreshToken );
129141 userUpdateServicePort .updateRemindDefault (user .getId (), signUpCommand .remindDefault ());
130142
131143 savePushSubscriptionPort .savePushSubscription (user , signUpCommand .fcmToken ());
@@ -135,7 +147,7 @@ public SignUpResponse signUpV3(SignUpCommandV3 signUpCommand) {
135147 Job job = Job .from (signUpCommand .job ());
136148 userUpdateServicePort .updateJob (user .getId (), job );
137149
138- return SignUpResponse .from (accessToken );
150+ return SignUpResponseV3 .from (accessToken , refreshToken );
139151 }
140152
141153 @ Transactional
@@ -149,11 +161,15 @@ public Mono<GoogleLoginResponseV3> getInfoAndTokenV3(String email, String pictur
149161 if (updatedUser .getRemindDefault () != null && updatedUser .getProfileImage () != null ) {
150162 log .info ("기존 사용자 로그인 성공: User ID {}" , updatedUser .getId ());
151163
152- //Access Token 발급
164+ //Access Token & Refresh Token 발급
153165 String accessToken = jwtProvider .createAccessToken (updatedUser .getId ());
166+ String refreshToken = jwtProvider .createRefreshToken (updatedUser .getId ());
167+
168+ saveRefreshTokenToRedis (updatedUser .getId (), refreshToken );
154169
155170 return Mono .just (GoogleLoginResponseV3 .loggedIn (
156- updatedUser .hasJob (), updatedUser .getId (), updatedUser .getEmail (), accessToken
171+ updatedUser .hasJob (), updatedUser .getId (), updatedUser .getEmail (), accessToken ,
172+ refreshToken
157173 ));
158174 } else {
159175 log .info ("기존 사용자 - 온보딩 미완료 유저 처리: User ID {}" , updatedUser .getId ());
@@ -185,6 +201,25 @@ public Mono<GoogleLoginResponseV3> getInfoAndTokenV3(String email, String pictur
185201 }));
186202 }
187203
204+ @ Transactional
205+ public SignUpResponseV3 getNewToken (String refreshToken ) {
206+ UUID userId = jwtProvider .getUserIdFromToken (refreshToken );
207+
208+ String redisKey = REDIS_REFRESH_TOKEN_PREFIX + userId .toString ();
209+ String savedToken = stringRedisTemplate .opsForValue ().get (redisKey );
210+ if (savedToken == null || !savedToken .equals (refreshToken )) {
211+ stringRedisTemplate .delete (redisKey );
212+ throw new InvalidTokenException ();
213+ }
214+
215+ String newAccessToken = jwtProvider .createAccessToken (userId );
216+ String newRefreshToken = jwtProvider .createRefreshToken (userId );
217+
218+ saveRefreshTokenToRedis (userId , newRefreshToken );
219+
220+ return SignUpResponseV3 .from (newAccessToken , newRefreshToken );
221+ }
222+
188223 private Mono <User > applyMissingUserInfo (User existingUser , String pictureUrl , String name ) {
189224 // 1. 이름 업데이트
190225 boolean nameUpdated = false ;
@@ -224,4 +259,13 @@ private String matchingProfileImage(LocalTime remindDefault) {
224259 return "IMAGE3" ;
225260 }
226261 }
262+
263+ private void saveRefreshTokenToRedis (UUID userId , String refreshToken ) {
264+ stringRedisTemplate .opsForValue ().set (
265+ "RT:" + userId .toString (),
266+ refreshToken ,
267+ refreshTokenExpirationPeriod ,
268+ java .util .concurrent .TimeUnit .MILLISECONDS
269+ );
270+ }
227271}
0 commit comments