|
@@ -21,13 +21,17 @@ import org.springframework.security.oauth2.client.authentication.OAuth2ClientAut
|
|
|
import org.springframework.security.oauth2.client.user.OAuth2UserService;
|
|
|
import org.springframework.security.oauth2.client.user.UserInfoRetriever;
|
|
|
import org.springframework.security.oauth2.client.user.nimbus.NimbusUserInfoRetriever;
|
|
|
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
|
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
|
|
import org.springframework.security.oauth2.oidc.client.authentication.OidcClientAuthenticationToken;
|
|
|
+import org.springframework.security.oauth2.oidc.core.OidcScope;
|
|
|
import org.springframework.security.oauth2.oidc.core.UserInfo;
|
|
|
import org.springframework.security.oauth2.oidc.core.user.DefaultOidcUser;
|
|
|
import org.springframework.security.oauth2.oidc.core.user.OidcUserAuthority;
|
|
|
import org.springframework.util.Assert;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.HashSet;
|
|
|
import java.util.Map;
|
|
|
import java.util.Set;
|
|
@@ -49,6 +53,8 @@ import java.util.Set;
|
|
|
*/
|
|
|
public class OidcUserService implements OAuth2UserService {
|
|
|
private UserInfoRetriever userInfoRetriever = new NimbusUserInfoRetriever();
|
|
|
+ private final Set<String> userInfoScopes = new HashSet<>(
|
|
|
+ Arrays.asList(OidcScope.PROFILE, OidcScope.EMAIL, OidcScope.ADDRESS, OidcScope.PHONE));
|
|
|
|
|
|
@Override
|
|
|
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
|
|
@@ -57,8 +63,11 @@ public class OidcUserService implements OAuth2UserService {
|
|
|
}
|
|
|
OidcClientAuthenticationToken oidcClientAuthentication = (OidcClientAuthenticationToken)clientAuthentication;
|
|
|
|
|
|
- Map<String, Object> userAttributes = this.getUserInfoRetriever().retrieve(oidcClientAuthentication);
|
|
|
- UserInfo userInfo = new UserInfo(userAttributes);
|
|
|
+ UserInfo userInfo = null;
|
|
|
+ if (this.shouldRetrieveUserInfo(oidcClientAuthentication)) {
|
|
|
+ Map<String, Object> userAttributes = this.getUserInfoRetriever().retrieve(oidcClientAuthentication);
|
|
|
+ userInfo = new UserInfo(userAttributes);
|
|
|
+ }
|
|
|
|
|
|
GrantedAuthority authority = new OidcUserAuthority(oidcClientAuthentication.getIdToken(), userInfo);
|
|
|
Set<GrantedAuthority> authorities = new HashSet<>();
|
|
@@ -75,4 +84,28 @@ public class OidcUserService implements OAuth2UserService {
|
|
|
Assert.notNull(userInfoRetriever, "userInfoRetriever cannot be null");
|
|
|
this.userInfoRetriever = userInfoRetriever;
|
|
|
}
|
|
|
+
|
|
|
+ private boolean shouldRetrieveUserInfo(OidcClientAuthenticationToken oidcClientAuthentication) {
|
|
|
+ // Auto-disabled if UserInfo Endpoint URI is not provided
|
|
|
+ if (StringUtils.isEmpty(oidcClientAuthentication.getClientRegistration().getProviderDetails()
|
|
|
+ .getUserInfoEndpoint().getUri())) {
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // The Claims requested by the profile, email, address, and phone scope values
|
|
|
+ // are returned from the UserInfo Endpoint (as described in Section 5.3.2),
|
|
|
+ // when a response_type value is used that results in an Access Token being issued.
|
|
|
+ // However, when no Access Token is issued, which is the case for the response_type=id_token,
|
|
|
+ // the resulting Claims are returned in the ID Token.
|
|
|
+ // The Authorization Code Grant Flow, which is response_type=code, results in an Access Token being issued.
|
|
|
+ if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(
|
|
|
+ oidcClientAuthentication.getClientRegistration().getAuthorizationGrantType())) {
|
|
|
+
|
|
|
+ // Return true if there is at least one match between the authorized scope(s) and UserInfo scope(s)
|
|
|
+ return oidcClientAuthentication.getAuthorizedScopes().stream().anyMatch(userInfoScopes::contains);
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|