-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCustomOAuth2UserService.java
More file actions
131 lines (97 loc) · 5.05 KB
/
CustomOAuth2UserService.java
File metadata and controls
131 lines (97 loc) · 5.05 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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package com.gpt.geumpumtabackend.global.oauth.service;
import com.gpt.geumpumtabackend.global.oauth.user.OAuth2Provider;
import com.gpt.geumpumtabackend.global.oauth.user.OAuth2UserInfo;
import com.gpt.geumpumtabackend.user.domain.User;
import com.gpt.geumpumtabackend.user.domain.UserRole;
import com.gpt.geumpumtabackend.user.repository.UserRepository;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
@Service
@Slf4j
@RequiredArgsConstructor
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
private final UserRepository userRepository;
@Transactional
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
// 1. registrationId 가져오기 (third-party id)
String registrationId = userRequest.getClientRegistration().getRegistrationId();
// 2. 유저 정보(attributes) 가져오기
Map<String, Object> oAuth2UserAttributes = loadAttributes(userRequest, registrationId);
// 3. userNameAttributeName 가져오기
String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails()
.getUserInfoEndpoint().getUserNameAttributeName();
String providerId = oAuth2UserAttributes.get(userNameAttributeName).toString();
// 4. 유저 정보 dto 생성
OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfo.of(registrationId, oAuth2UserAttributes);
// 5. 회원가입 및 로그인
User user = getOrSave(oAuth2UserInfo, registrationId, providerId);
log.info("Access Token: {}", userRequest.getAccessToken().getTokenValue());
// 추가적인 토큰 정보 로깅
log.info("Token Type: {}", userRequest.getAccessToken().getTokenType());
log.info("Scopes: {}", userRequest.getAccessToken().getScopes());
log.info("Expires At: {}", userRequest.getAccessToken().getExpiresAt());
// 클라이언트 등록 정보 로깅
log.info("Registration ID: {}", userRequest.getClientRegistration().getRegistrationId());
return new OAuth2UserPrincipal(user, oAuth2UserAttributes, userNameAttributeName);
}
private Map<String, Object> loadAttributes(OAuth2UserRequest userRequest, String registrationId) {
if(registrationId.equals("apple")) {
return loadAppleAttributes(userRequest);
}
return super.loadUser(userRequest).getAttributes();
}
private Map<String, Object> loadAppleAttributes(OAuth2UserRequest userRequest) {
Object idTokenObj = userRequest.getAdditionalParameters().get("id_token");
if (idTokenObj == null) {
throw new OAuth2AuthenticationException("Apple id_token is missing in additionalParameters");
}
String idToken = idTokenObj.toString();
try {
SignedJWT signedJWT = SignedJWT.parse(idToken);
JWTClaimsSet claims = signedJWT.getJWTClaimsSet();
// claims.getClaims()는 Map<String, Object>를 반환
Map<String, Object> attributes = new HashMap<>(claims.getClaims());
// 로그로 한 번 확인해보고 싶으면:
log.info("Apple id_token claims: {}", attributes);
return attributes;
} catch (ParseException e) {
throw new OAuth2AuthenticationException("Failed to parse Apple id_token");
}
}
private User getOrSave(OAuth2UserInfo oAuth2UserInfo, String registrationId, String providerId) {
OAuth2Provider provider = resolveProvider(registrationId);
return userRepository.findByProviderAndProviderId(provider, providerId)
.orElseGet(() -> createNewUser(oAuth2UserInfo, provider, providerId));
}
private OAuth2Provider resolveProvider(String registrationId) {
return switch (registrationId) {
case "google" -> OAuth2Provider.GOOGLE;
case "kakao" -> OAuth2Provider.KAKAO;
case "apple" -> OAuth2Provider.APPLE;
default -> throw new IllegalArgumentException("Unsupported provider: " + registrationId);
};
}
private User createNewUser(OAuth2UserInfo info, OAuth2Provider provider, String providerId) {
User user = User.builder()
.email(info.email())
.role(UserRole.GUEST)
.name(info.name())
.picture(info.profile())
.provider(provider)
.providerId(providerId)
.build();
return userRepository.save(user);
}
}