|
|
|
@ -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.OAuth2UserService; |
|
|
|
import org.springframework.security.oauth2.client.user.UserInfoRetriever; |
|
|
|
import org.springframework.security.oauth2.client.user.UserInfoRetriever; |
|
|
|
import org.springframework.security.oauth2.client.user.nimbus.NimbusUserInfoRetriever; |
|
|
|
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.core.user.OAuth2User; |
|
|
|
import org.springframework.security.oauth2.oidc.client.authentication.OidcClientAuthenticationToken; |
|
|
|
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.UserInfo; |
|
|
|
import org.springframework.security.oauth2.oidc.core.user.DefaultOidcUser; |
|
|
|
import org.springframework.security.oauth2.oidc.core.user.DefaultOidcUser; |
|
|
|
import org.springframework.security.oauth2.oidc.core.user.OidcUserAuthority; |
|
|
|
import org.springframework.security.oauth2.oidc.core.user.OidcUserAuthority; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
|
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.Arrays; |
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Set; |
|
|
|
import java.util.Set; |
|
|
|
@ -49,6 +53,8 @@ import java.util.Set; |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class OidcUserService implements OAuth2UserService { |
|
|
|
public class OidcUserService implements OAuth2UserService { |
|
|
|
private UserInfoRetriever userInfoRetriever = new NimbusUserInfoRetriever(); |
|
|
|
private UserInfoRetriever userInfoRetriever = new NimbusUserInfoRetriever(); |
|
|
|
|
|
|
|
private final Set<String> userInfoScopes = new HashSet<>( |
|
|
|
|
|
|
|
Arrays.asList(OidcScope.PROFILE, OidcScope.EMAIL, OidcScope.ADDRESS, OidcScope.PHONE)); |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException { |
|
|
|
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException { |
|
|
|
@ -57,8 +63,11 @@ public class OidcUserService implements OAuth2UserService { |
|
|
|
} |
|
|
|
} |
|
|
|
OidcClientAuthenticationToken oidcClientAuthentication = (OidcClientAuthenticationToken)clientAuthentication; |
|
|
|
OidcClientAuthenticationToken oidcClientAuthentication = (OidcClientAuthenticationToken)clientAuthentication; |
|
|
|
|
|
|
|
|
|
|
|
Map<String, Object> userAttributes = this.getUserInfoRetriever().retrieve(oidcClientAuthentication); |
|
|
|
UserInfo userInfo = null; |
|
|
|
UserInfo userInfo = new UserInfo(userAttributes); |
|
|
|
if (this.shouldRetrieveUserInfo(oidcClientAuthentication)) { |
|
|
|
|
|
|
|
Map<String, Object> userAttributes = this.getUserInfoRetriever().retrieve(oidcClientAuthentication); |
|
|
|
|
|
|
|
userInfo = new UserInfo(userAttributes); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
GrantedAuthority authority = new OidcUserAuthority(oidcClientAuthentication.getIdToken(), userInfo); |
|
|
|
GrantedAuthority authority = new OidcUserAuthority(oidcClientAuthentication.getIdToken(), userInfo); |
|
|
|
Set<GrantedAuthority> authorities = new HashSet<>(); |
|
|
|
Set<GrantedAuthority> authorities = new HashSet<>(); |
|
|
|
@ -75,4 +84,28 @@ public class OidcUserService implements OAuth2UserService { |
|
|
|
Assert.notNull(userInfoRetriever, "userInfoRetriever cannot be null"); |
|
|
|
Assert.notNull(userInfoRetriever, "userInfoRetriever cannot be null"); |
|
|
|
this.userInfoRetriever = userInfoRetriever; |
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|