2
2
3
3
import static com .readyvery .readyverydemo .config .OauthConfig .*;
4
4
5
+ import java .nio .charset .StandardCharsets ;
6
+ import java .util .Base64 ;
5
7
import java .util .Collections ;
8
+ import java .util .HashMap ;
6
9
import java .util .Map ;
7
10
8
11
import org .springframework .security .core .authority .SimpleGrantedAuthority ;
9
12
import org .springframework .security .oauth2 .client .userinfo .DefaultOAuth2UserService ;
10
13
import org .springframework .security .oauth2 .client .userinfo .OAuth2UserRequest ;
11
14
import org .springframework .security .oauth2 .client .userinfo .OAuth2UserService ;
12
15
import org .springframework .security .oauth2 .core .OAuth2AuthenticationException ;
16
+ import org .springframework .security .oauth2 .core .user .DefaultOAuth2User ;
13
17
import org .springframework .security .oauth2 .core .user .OAuth2User ;
14
18
import org .springframework .stereotype .Service ;
15
19
20
+ import com .fasterxml .jackson .core .JsonProcessingException ;
21
+ import com .fasterxml .jackson .databind .ObjectMapper ;
16
22
import com .readyvery .readyverydemo .domain .SocialType ;
17
23
import com .readyvery .readyverydemo .domain .UserInfo ;
18
24
import com .readyvery .readyverydemo .domain .repository .UserRepository ;
@@ -31,42 +37,58 @@ public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequ
31
37
32
38
@ Override
33
39
public OAuth2User loadUser (OAuth2UserRequest userRequest ) throws OAuth2AuthenticationException {
34
- System .out .println ("userRequest = " + userRequest );
40
+ String registrationId = userRequest .getClientRegistration ().getRegistrationId ();
41
+ OAuth2UserService <OAuth2UserRequest , OAuth2User > delegate = new DefaultOAuth2UserService ();
42
+
43
+ Map <String , Object > attributes ;
35
44
/**
36
45
* DefaultOAuth2UserService 객체를 생성하여, loadUser(userRequest)를 통해 DefaultOAuth2User 객체를 생성 후 반환
37
46
* DefaultOAuth2UserService의 loadUser()는 소셜 로그인 API의 사용자 정보 제공 URI로 요청을 보내서
38
47
* 사용자 정보를 얻은 후, 이를 통해 DefaultOAuth2User 객체를 생성 후 반환한다.
39
48
* 결과적으로, OAuth2User는 OAuth 서비스에서 가져온 유저 정보를 담고 있는 유저
40
49
*/
41
- OAuth2UserService <OAuth2UserRequest , OAuth2User > delegate = new DefaultOAuth2UserService ();
42
- OAuth2User oAuth2User = delegate .loadUser (userRequest );
43
-
44
- /**
45
- * userRequest에서 registrationId 추출 후 registrationId으로 SocialType 저장
46
- * http://localhost:8080/oauth2/authorization/kakao에서 kakao가 registrationId
47
- * userNameAttributeName은 이후에 nameAttributeKey로 설정된다.
48
- */
49
- String registrationId = userRequest .getClientRegistration ().getRegistrationId ();
50
- SocialType socialType = getSocialType (registrationId );
51
-
52
- String userNameAttributeName = userRequest .getClientRegistration ()
53
- .getProviderDetails ().getUserInfoEndpoint ().getUserNameAttributeName (); // OAuth2 로그인 시 키(PK)가 되는 값
54
- Map <String , Object > attributes = oAuth2User .getAttributes (); // 소셜 로그인에서 API가 제공하는 userInfo의 Json 값(유저 정보들)
55
-
56
- // socialType에 따라 유저 정보를 통해 OAuthAttributes 객체 생성
57
-
58
- OAuthAttributes extractAttributes = OAuthAttributes .of (socialType , userNameAttributeName , attributes );
59
-
60
- UserInfo createdUser = getUser (extractAttributes , socialType ); // getUser() 메소드로 User 객체 생성 후 반환
61
-
62
- // DefaultOAuth2User를 구현한 CustomOAuth2User 객체를 생성해서 반환
63
- return new CustomOAuth2User (
64
- Collections .singleton (new SimpleGrantedAuthority (createdUser .getRole ().getKey ())),
65
- attributes ,
66
- extractAttributes .getNameAttributeKey (),
67
- createdUser .getEmail (),
68
- createdUser .getRole ()
69
- );
50
+ if (registrationId .contains (APPLE_NAME )) {
51
+ String idToken = userRequest .getAdditionalParameters ().get ("id_token" ).toString ();
52
+ attributes = decodeJwtTokenPayload (idToken );
53
+ attributes .put ("id_token" , idToken );
54
+ Map <String , Object > userAttributes = new HashMap <>();
55
+ userAttributes .put ("resultcode" , "00" );
56
+ userAttributes .put ("message" , "success" );
57
+ userAttributes .put ("response" , attributes );
58
+
59
+ return new DefaultOAuth2User (Collections .singleton (new SimpleGrantedAuthority ("ROLE_GUEST" )),
60
+ userAttributes , "response" );
61
+ } else {
62
+ OAuth2User oAuth2User = delegate .loadUser (userRequest );
63
+ attributes = oAuth2User .getAttributes ();
64
+
65
+ /**
66
+ * userRequest에서 registrationId 추출 후 registrationId으로 SocialType 저장
67
+ * http://localhost:8080/oauth2/authorization/kakao에서 kakao가 registrationId
68
+ * userNameAttributeName은 이후에 nameAttributeKey로 설정된다.
69
+ */
70
+
71
+ SocialType socialType = getSocialType (registrationId );
72
+
73
+ String userNameAttributeName = userRequest .getClientRegistration ()
74
+ .getProviderDetails ().getUserInfoEndpoint ().getUserNameAttributeName (); // OAuth2 로그인 시 키(PK)가 되는값
75
+ attributes = oAuth2User .getAttributes (); // 소셜 로그인에서 API가 제공하는 userInfo의 Json 값(유저 정보들)
76
+
77
+ // socialType에 따라 유저 정보를 통해 OAuthAttributes 객체 생성
78
+
79
+ OAuthAttributes extractAttributes = OAuthAttributes .of (socialType , userNameAttributeName , attributes );
80
+
81
+ UserInfo createdUser = getUser (extractAttributes , socialType ); // getUser() 메소드로 User 객체 생성 후 반환
82
+
83
+ // DefaultOAuth2User를 구현한 CustomOAuth2User 객체를 생성해서 반환
84
+ return new CustomOAuth2User (
85
+ Collections .singleton (new SimpleGrantedAuthority (createdUser .getRole ().getKey ())),
86
+ attributes ,
87
+ extractAttributes .getNameAttributeKey (),
88
+ createdUser .getEmail (),
89
+ createdUser .getRole ()
90
+ );
91
+ }
70
92
}
71
93
72
94
private SocialType getSocialType (String registrationId ) {
@@ -103,4 +125,23 @@ private UserInfo saveUser(OAuthAttributes attributes, SocialType socialType) {
103
125
UserInfo createdUser = attributes .toEntity (socialType , attributes .getOauth2UserInfo ());
104
126
return userRepository .save (createdUser );
105
127
}
128
+
129
+ private Map <String , Object > decodeJwtTokenPayload (String jwtToken ) {
130
+ Map <String , Object > jwtClaims = new HashMap <>();
131
+ try {
132
+ String [] parts = jwtToken .split ("\\ ." );
133
+ Base64 .Decoder decoder = Base64 .getUrlDecoder ();
134
+
135
+ byte [] decodedBytes = decoder .decode (parts [1 ].getBytes (StandardCharsets .UTF_8 ));
136
+ String decodedString = new String (decodedBytes , StandardCharsets .UTF_8 );
137
+ ObjectMapper mapper = new ObjectMapper ();
138
+
139
+ Map <String , Object > map = mapper .readValue (decodedString , Map .class );
140
+ jwtClaims .putAll (map );
141
+
142
+ } catch (JsonProcessingException e ) {
143
+ // logger.error("decodeJwtToken: {}-{} / jwtToken : {}", e.getMessage(), e.getCause(), jwtToken);
144
+ }
145
+ return jwtClaims ;
146
+ }
106
147
}
0 commit comments