-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathOAuth2SuccessHandler.java
More file actions
101 lines (80 loc) · 4.76 KB
/
OAuth2SuccessHandler.java
File metadata and controls
101 lines (80 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package com.DecodEat.global.config.oauth;
import com.DecodEat.domain.refreshToken.entity.RefreshToken;
import com.DecodEat.domain.refreshToken.repository.RefreshTokenRepository;
import com.DecodEat.domain.users.entity.User;
import com.DecodEat.domain.users.service.UserService;
import com.DecodEat.global.config.jwt.JwtTokenProvider;
import com.DecodEat.global.util.CookieUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
import java.io.IOException;
import java.time.Duration;
import java.util.Map;
@RequiredArgsConstructor
@Component
public class OAuth2SuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
public static final String REFRESH_TOKEN_COOKIE_NAME = "refresh_token";
public static final String ACCESS_TOKEN_COOKIE_NAME = "access_token";
public static final Duration REFRESH_TOKEN_DURATION = Duration.ofDays(14);
public static final Duration ACCESS_TOKEN_DURATION = Duration.ofHours(1);
public static final String REDIRECT_PATH = "/oauth2/redirect"; // 프론트엔드로 리다이렉트할 경로
private final JwtTokenProvider tokenProvider;
private final RefreshTokenRepository refreshTokenRepository;
private final OAuth2AuthorizationRequestBasedOnCookieRepository authorizationRequestRepository;
private final UserService userService;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();
Map<String, Object> attributes = oAuth2User.getAttributes();
Map<String, Object> kakaoAccount = (Map<String, Object>) attributes.get("kakao_account");
String email = (String) kakaoAccount.get("email");
User user = userService.findByEmail(email);
// 1. 리프레시 토큰 생성 -> 저장 -> 쿠키에 저장
String refreshToken = tokenProvider.generateToken(user, REFRESH_TOKEN_DURATION);
saveRefreshToken(user.getId(), refreshToken);
addRefreshTokenToCookie(request, response, refreshToken);
// 2. 액세스 토큰 생성
String accessToken = tokenProvider.generateToken(user, ACCESS_TOKEN_DURATION);
addAccessTokenToCookie(request, response, accessToken);
String targetUrl = getTargetUrl(accessToken);
// 3. 인증 관련 설정값, 쿠키 제거
clearAuthenticationAttributes(request, response);
// 4. 리다이렉트
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}
// 생성된 리프레시 토큰을 전달받아 DB에 저장
private void saveRefreshToken(Long userId, String newRefreshToken) {
RefreshToken refreshToken = refreshTokenRepository.findByUserId(userId)
.map(entity -> entity.updateRefreshToken(newRefreshToken)) // Setter 대신 별도의 메서드 두고 사용
.orElse(new RefreshToken(userId, newRefreshToken));
refreshTokenRepository.save(refreshToken);
}
private void addAccessTokenToCookie(HttpServletRequest request, HttpServletResponse response, String accessToken) {
int cookieMaxAge = (int) ACCESS_TOKEN_DURATION.toSeconds();
CookieUtil.deleteCookie(request, response, ACCESS_TOKEN_COOKIE_NAME);
CookieUtil.addCookie(response, ACCESS_TOKEN_COOKIE_NAME, accessToken, cookieMaxAge);
}
// 생성된 리프레시 토큰을 쿠키에 저장
private void addRefreshTokenToCookie(HttpServletRequest request, HttpServletResponse response, String refreshToken) {
int cookieMaxAge = (int) REFRESH_TOKEN_DURATION.toSeconds();
CookieUtil.deleteCookie(request, response, REFRESH_TOKEN_COOKIE_NAME);
CookieUtil.addCookie(response, REFRESH_TOKEN_COOKIE_NAME, refreshToken, cookieMaxAge);
}
// 인증 관련 설정값, 쿠키 제거
private void clearAuthenticationAttributes(HttpServletRequest request, HttpServletResponse response) {
super.clearAuthenticationAttributes(request);
authorizationRequestRepository.removeAuthorizationRequestCookies(request, response);
}
// 액세스 토큰을 리다이렉트 경로에 파라미터로 추가
private String getTargetUrl(String token) {
return UriComponentsBuilder.fromUriString("https://decodeat.netlify.app") //todo:로그인 후 스웨거화면
.build()
.toUriString();
}
}