1
1
package eu .solven .kumite .security .oauth2 ;
2
2
3
3
import java .net .URI ;
4
+ import java .net .URISyntaxException ;
5
+ import java .net .URL ;
4
6
7
+ import org .springframework .security .core .authority .SimpleGrantedAuthority ;
5
8
import org .springframework .security .oauth2 .client .userinfo .DefaultReactiveOAuth2UserService ;
6
9
import org .springframework .security .oauth2 .client .userinfo .OAuth2UserRequest ;
7
10
import org .springframework .security .oauth2 .core .OAuth2AuthenticationException ;
13
16
import eu .solven .kumite .account .KumiteUserRaw .KumiteUserRawBuilder ;
14
17
import eu .solven .kumite .account .KumiteUserRawRaw ;
15
18
import eu .solven .kumite .account .KumiteUsersRegistry ;
19
+ import eu .solven .kumite .account .login .IKumiteTestConstants ;
16
20
import graphql .VisibleForTesting ;
17
21
import lombok .RequiredArgsConstructor ;
18
22
import lombok .SneakyThrows ;
33
37
@ Service
34
38
@ RequiredArgsConstructor
35
39
public class KumiteOAuth2UserService extends DefaultReactiveOAuth2UserService {
40
+ public static final String PROVIDERID_GITHUB = "github" ;
41
+ public static final String PROVIDERID_GOOGLE = "google" ;
42
+
43
+ @ Deprecated
44
+ public static final String PROVIDERID_TEST = IKumiteTestConstants .PROVIDERID_TEST ;
36
45
37
46
// private final AccountsStore accountsStore;
38
47
final KumiteUsersRegistry usersRegistry ;
@@ -57,23 +66,18 @@ private Mono<OAuth2User> processOAuth2User(OAuth2UserRequest oAuth2UserRequest,
57
66
// The following comment can be used to register new unittest on new registration
58
67
// new ObjectMapper().writeValueAsString(userFromProvider.getAttributes());
59
68
60
- String registrationId = oAuth2UserRequest .getClientRegistration ().getRegistrationId ();
61
-
62
- String keyForSub = switch (registrationId ) {
63
- case "github" :
64
- yield "id" ;
65
- default :
66
- throw new IllegalArgumentException ("Unexpected value: " + registrationId );
67
- };
69
+ KumiteUserRawRaw rawRaw = oauth2ToRawRaw (userFromProvider );
68
70
69
- KumiteUserRawRaw rawRaw = KumiteUserRawRaw . builder ()
70
- . providerId ( registrationId )
71
- . sub ( userFromProvider . getAttributes (). get ( keyForSub ). toString ())
72
- . build ();
71
+ String registrationId = oAuth2UserRequest . getClientRegistration (). getRegistrationId ();
72
+ if (! registrationId . equals ( rawRaw . getProviderId ())) {
73
+ throw new IllegalStateException ( "Inconsistent providerId inference from OAuth2User" );
74
+ }
73
75
74
76
String keyForPicture = switch (registrationId ) {
75
- case "github" :
77
+ case PROVIDERID_GITHUB :
76
78
yield "avatar_url" ;
79
+ case PROVIDERID_GOOGLE :
80
+ yield "picture" ;
77
81
default :
78
82
throw new IllegalArgumentException ("Unexpected value: " + registrationId );
79
83
};
@@ -97,4 +101,65 @@ private Mono<OAuth2User> processOAuth2User(OAuth2UserRequest oAuth2UserRequest,
97
101
98
102
}
99
103
104
+ public static KumiteUserRawRaw oauth2ToRawRaw (OAuth2User o ) {
105
+ String providerId = guessProviderId (o );
106
+ String sub = getSub (providerId , o );
107
+ KumiteUserRawRaw rawRaw = KumiteUserRawRaw .builder ().providerId (providerId ).sub (sub ).build ();
108
+ return rawRaw ;
109
+ }
110
+
111
+ private static String getSub (String providerId , OAuth2User o ) {
112
+ if (PROVIDERID_GITHUB .equals (providerId )) {
113
+ Object id = o .getAttribute ("id" );
114
+ if (id == null ) {
115
+ throw new IllegalStateException ("Invalid id: " + id );
116
+ }
117
+ return id .toString ();
118
+ } else if (PROVIDERID_GOOGLE .equals (providerId )) {
119
+ Object sub = o .getAttribute ("sub" );
120
+ if (sub == null ) {
121
+ throw new IllegalStateException ("Invalid sub: " + sub );
122
+ }
123
+ return sub .toString ();
124
+ } else if (PROVIDERID_TEST .equals (providerId )) {
125
+ Object id = o .getAttribute ("id" );
126
+ if (id == null ) {
127
+ throw new IllegalStateException ("Invalid sub: " + id );
128
+ }
129
+ return id .toString ();
130
+ } else {
131
+ throw new IllegalStateException ("Not managed providerId: " + providerId );
132
+ }
133
+ }
134
+
135
+ private static String guessProviderId (OAuth2User o ) {
136
+ if (isGoogle (o )) {
137
+ return PROVIDERID_GOOGLE ;
138
+ } else if (PROVIDERID_TEST .equals (o .getAttribute ("providerId" ))) {
139
+ return PROVIDERID_TEST ;
140
+ }
141
+ return PROVIDERID_GITHUB ;
142
+ }
143
+
144
+ private static boolean isGoogle (OAuth2User o ) {
145
+ if (o .getAuthorities ()
146
+ .contains (new SimpleGrantedAuthority ("SCOPE_https://www.googleapis.com/auth/userinfo.email" ))) {
147
+ return true ;
148
+ }
149
+
150
+ // TODO Unclear when we receive iss or not (Changed around introducing
151
+ // SocialWebFluxSecurity.oidcReactiveOAuth2UserService)
152
+ URL issuer = (URL ) o .getAttribute ("iss" );
153
+ if (issuer == null ) {
154
+ return false ;
155
+ }
156
+ URI uri ;
157
+ try {
158
+ uri = issuer .toURI ();
159
+ } catch (URISyntaxException e ) {
160
+ throw new IllegalStateException ("Invalid iss: `%s`" .formatted (issuer ), e );
161
+ }
162
+ return "https://accounts.google.com" .equals (uri .toASCIIString ());
163
+ }
164
+
100
165
}
0 commit comments