-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCustomOAuth2UserService.java
More file actions
99 lines (79 loc) · 4.04 KB
/
CustomOAuth2UserService.java
File metadata and controls
99 lines (79 loc) · 4.04 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
package bitnagil.bitnagil_backend.auth.kakao.service;
import java.util.Collections;
import java.util.Map;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import bitnagil.bitnagil_backend.auth.kakao.domain.CustomOAuth2User;
import bitnagil.bitnagil_backend.auth.kakao.domain.OAuth2Attribute;
import bitnagil.bitnagil_backend.global.errorcode.ErrorCode;
import bitnagil.bitnagil_backend.global.exception.CustomException;
import bitnagil.bitnagil_backend.user.repository.UserRepository;
import bitnagil.bitnagil_backend.user.domain.enums.SocialType;
import bitnagil.bitnagil_backend.user.domain.User;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* OAuth2 로그인 과정에서 사용자 정보를 처리하는 서비스 클래스입니다.
*
* Spring Security의 {@link OAuth2UserService}를 구현하여,
* 외부 소셜 로그인(Kakao 등) 후 사용자 정보를 파싱하고 DB에 저장 또는 조회하여
* 인증된 {@link CustomOAuth2User} 객체를 반환합니다.
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
private static final String KAKAO = "kakao";
private final UserRepository userRepository;
/**
* OAuth2 로그인 시 호출되는 메서드로, 외부 서비스에서 사용자 정보를 받아와 처리합니다.
*
* @param userRequest OAuth2 로그인 요청 정보
* @return 인증된 사용자 정보를 담은 {@link CustomOAuth2User}
*/
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
OAuth2User oAuth2User = delegate.loadUser(userRequest);
String registrationId = userRequest.getClientRegistration().getRegistrationId();
SocialType socialType = getSocialType(registrationId);
String userNameAttributeName = getUserNameAttributeName(userRequest);
Map<String, Object> attributes = oAuth2User.getAttributes();
OAuth2Attribute extractAttributes = OAuth2Attribute.of(socialType, userNameAttributeName, attributes);
// 기존 회원 조회 또는 신규 회원 저장
User createdUser = getMember(extractAttributes, socialType);
return new CustomOAuth2User(
Collections.singleton(new SimpleGrantedAuthority(createdUser.getRole().getDescription())),
attributes, extractAttributes.getNameAttributeKey(), createdUser.getUserId(), createdUser.getRole());
}
private String getUserNameAttributeName(final OAuth2UserRequest userRequest) {
return userRequest.getClientRegistration()
.getProviderDetails()
.getUserInfoEndpoint()
.getUserNameAttributeName();
}
private SocialType getSocialType(String registrationId) {
if (KAKAO.equals(registrationId)) {
return SocialType.KAKAO;
}
return SocialType.APPLE;
}
private User getMember(OAuth2Attribute attributes, SocialType socialType) {
User findUser = userRepository
.findBySocialTypeAndSocialId(socialType, attributes.getSocialId())
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_USER));
if (findUser == null) {
return saveMember(attributes, socialType);
}
return findUser;
}
private User saveMember(OAuth2Attribute attributes, SocialType socialType) {
User createdUser = attributes.toEntity(socialType);
return userRepository.save(createdUser);
}
}