Skip to content

Commit a495291

Browse files
committed
Fix duplicate Google relogin handling
1 parent 683411f commit a495291

4 files changed

Lines changed: 50 additions & 17 deletions

File tree

ontime-back/src/main/java/devkor/ontime_back/global/jwt/JwtAuthenticationFilter.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,12 @@ public void checkAccessTokenAndAuthentication(HttpServletRequest request, HttpSe
107107
FilterChain filterChain) throws ServletException, IOException {
108108
log.info("checkAccessTokenAndAuthentication() 호출");
109109
jwtTokenProvider.extractAccessToken(request)
110-
.ifPresent(accessToken -> {
111-
jwtTokenProvider.extractEmail(accessToken)
112-
.ifPresent(email -> userRepository.findByEmail(email)
113-
.ifPresent(this::saveAuthentication)
114-
);
115-
116-
jwtTokenProvider.extractUserId(accessToken)
117-
.ifPresent(userId -> log.info("추출된 userId: {}", userId));
118-
});
110+
.ifPresent(accessToken -> jwtTokenProvider.extractUserId(accessToken)
111+
.ifPresent(userId -> {
112+
log.info("추출된 userId: {}", userId);
113+
userRepository.findById(userId)
114+
.ifPresent(this::saveAuthentication);
115+
}));
119116

120117
filterChain.doFilter(request, response);
121118
}
@@ -192,4 +189,4 @@ private void handleInvalidTokenException(HttpServletResponse response, InvalidTo
192189
response.getWriter().write(objectMapper.writeValueAsString(errorResponse));
193190
}
194191
}
195-
}
192+
}

ontime-back/src/main/java/devkor/ontime_back/global/jwt/JwtTokenProvider.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public String createRefreshToken() {
7171
return JWT.create()
7272
.withSubject(REFRESH_TOKEN_SUBJECT)
7373
.withExpiresAt(new Date(now.getTime() + refreshTokenExpirationPeriod))
74+
.withJWTId(UUID.randomUUID().toString())
7475
.sign(Algorithm.HMAC512(secretKey));
7576
}
7677

@@ -199,4 +200,4 @@ public String createExpiredAccessToken(String email) {
199200
.sign(Algorithm.HMAC512(secretKey));
200201
}
201202

202-
}
203+
}

ontime-back/src/main/java/devkor/ontime_back/global/oauth/google/GoogleLoginFilter.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
1919

2020
import java.io.IOException;
21+
import java.util.Map;
2122
import java.util.Optional;
23+
import java.util.concurrent.ConcurrentHashMap;
2224

2325
@Slf4j
2426
public class GoogleLoginFilter extends AbstractAuthenticationProcessingFilter {
27+
private static final Map<String, Object> LOGIN_LOCKS = new ConcurrentHashMap<>();
28+
2529
private final UserRepository userRepository;
2630
private final GoogleLoginService googleLoginService;
2731

@@ -42,13 +46,16 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ
4246
GoogleIdToken.Payload googlePayload = googleLoginService.verifyIdentityToken(oAuthGoogleRequestDto.getIdToken());
4347
String googleUserId = googlePayload.getSubject();
4448

45-
Optional<User> existingUser = userRepository.findBySocialTypeAndSocialId(SocialType.GOOGLE, googleUserId);
49+
Object loginLock = LOGIN_LOCKS.computeIfAbsent(googleUserId, key -> new Object());
50+
synchronized (loginLock) {
51+
Optional<User> existingUser = userRepository.findBySocialTypeAndSocialId(SocialType.GOOGLE, googleUserId);
4652

47-
if (existingUser.isPresent()) {
48-
return googleLoginService.handleLogin(oAuthGoogleRequestDto, existingUser.get(), response);
49-
} else {
50-
OAuthGoogleUserDto oAuthGoogleUserDto = new OAuthGoogleUserDto(googleUserId, (String) googlePayload.get("name"), (String) googlePayload.get("picture"), googlePayload.getEmail());
51-
return googleLoginService.handleRegister(oAuthGoogleRequestDto, oAuthGoogleUserDto, response);
53+
if (existingUser.isPresent()) {
54+
return googleLoginService.handleLogin(oAuthGoogleRequestDto, existingUser.get(), response);
55+
} else {
56+
OAuthGoogleUserDto oAuthGoogleUserDto = new OAuthGoogleUserDto(googleUserId, (String) googlePayload.get("name"), (String) googlePayload.get("picture"), googlePayload.getEmail());
57+
return googleLoginService.handleRegister(oAuthGoogleRequestDto, oAuthGoogleUserDto, response);
58+
}
5259
}
5360

5461
} catch (Exception e) {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package devkor.ontime_back.global.jwt;
2+
3+
import devkor.ontime_back.repository.UserRepository;
4+
import org.junit.jupiter.api.DisplayName;
5+
import org.junit.jupiter.api.Test;
6+
import org.springframework.test.util.ReflectionTestUtils;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
import static org.mockito.Mockito.mock;
10+
11+
class JwtTokenProviderTest {
12+
13+
@DisplayName("동일한 시각에 발급한 리프레시 토큰도 서로 다르다")
14+
@Test
15+
void createRefreshTokenGeneratesUniqueTokens() {
16+
// given
17+
JwtTokenProvider jwtTokenProvider = new JwtTokenProvider(mock(UserRepository.class));
18+
ReflectionTestUtils.setField(jwtTokenProvider, "secretKey", "test-secret-key-that-is-long-enough");
19+
ReflectionTestUtils.setField(jwtTokenProvider, "refreshTokenExpirationPeriod", 3600000L);
20+
21+
// when
22+
String refreshToken1 = jwtTokenProvider.createRefreshToken();
23+
String refreshToken2 = jwtTokenProvider.createRefreshToken();
24+
25+
// then
26+
assertThat(refreshToken1).isNotEqualTo(refreshToken2);
27+
}
28+
}

0 commit comments

Comments
 (0)