Add userNameAttributeName to ClientRegistration

Fixes gh-4580
This commit is contained in:
Joe Grandja 2017-09-26 21:55:19 -04:00
parent 7fb3093617
commit 38be35677d
8 changed files with 69 additions and 44 deletions

View File

@ -135,6 +135,7 @@ final class AuthorizationCodeAuthenticationFilterConfigurer<H extends HttpSecuri
@Override @Override
public void init(H http) throws Exception { public void init(H http) throws Exception {
this.initUserNameAttributeNames();
AuthorizationCodeAuthenticationProvider authenticationProvider = new AuthorizationCodeAuthenticationProvider( AuthorizationCodeAuthenticationProvider authenticationProvider = new AuthorizationCodeAuthenticationProvider(
this.getAuthorizationCodeTokenExchanger(), this.getAccessTokenRepository(), this.getAuthorizationCodeTokenExchanger(), this.getAccessTokenRepository(),
this.getProviderJwtDecoderRegistry(), this.getUserInfoService()); this.getProviderJwtDecoderRegistry(), this.getUserInfoService());
@ -162,6 +163,20 @@ final class AuthorizationCodeAuthenticationFilterConfigurer<H extends HttpSecuri
this.authorizationResponseMatcher : this.getAuthenticationFilter().getAuthorizationResponseMatcher()); this.authorizationResponseMatcher : this.getAuthenticationFilter().getAuthorizationResponseMatcher());
} }
private void initUserNameAttributeNames() {
OAuth2LoginConfigurer.getClientRegistrationRepository(this.getBuilder()).getRegistrations().forEach(registration -> {
if (StringUtils.hasText(registration.getProviderDetails().getUserInfoEndpoint().getUri()) &&
StringUtils.hasText(registration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName())) {
URI userInfoUri = URI.create(registration.getProviderDetails().getUserInfoEndpoint().getUri());
if (!this.userNameAttributeNames.containsKey(userInfoUri)) {
this.userNameAttributeNames.put(
userInfoUri, registration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName());
}
}
});
}
private AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> getAuthorizationCodeTokenExchanger() { private AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> getAuthorizationCodeTokenExchanger() {
if (this.authorizationCodeTokenExchanger == null) { if (this.authorizationCodeTokenExchanger == null) {
this.authorizationCodeTokenExchanger = new NimbusAuthorizationCodeTokenExchanger(); this.authorizationCodeTokenExchanger = new NimbusAuthorizationCodeTokenExchanger();
@ -192,7 +207,7 @@ final class AuthorizationCodeAuthenticationFilterConfigurer<H extends HttpSecuri
)); ));
providerMetadata.setAuthorizationEndpoint(this.toURL(providerDetails.getAuthorizationUri())); providerMetadata.setAuthorizationEndpoint(this.toURL(providerDetails.getAuthorizationUri()));
providerMetadata.setTokenEndpoint(this.toURL(providerDetails.getTokenUri())); providerMetadata.setTokenEndpoint(this.toURL(providerDetails.getTokenUri()));
providerMetadata.setUserInfoEndpoint(this.toURL(providerDetails.getUserInfoUri())); providerMetadata.setUserInfoEndpoint(this.toURL(providerDetails.getUserInfoEndpoint().getUri()));
providerMetadata.setJwkSetUri(this.toURL(providerDetails.getJwkSetUri())); providerMetadata.setJwkSetUri(this.toURL(providerDetails.getJwkSetUri()));
NimbusJwtDecoderJwkSupport nimbusJwtDecoderJwkSupport = NimbusJwtDecoderJwkSupport nimbusJwtDecoderJwkSupport =
new NimbusJwtDecoderJwkSupport(providerDetails.getJwkSetUri()); new NimbusJwtDecoderJwkSupport(providerDetails.getJwkSetUri());

View File

@ -121,7 +121,7 @@ public class ClientRegistration {
public class ProviderDetails { public class ProviderDetails {
private String authorizationUri; private String authorizationUri;
private String tokenUri; private String tokenUri;
private String userInfoUri; private UserInfoEndpoint userInfoEndpoint = new UserInfoEndpoint();
private String jwkSetUri; private String jwkSetUri;
protected ProviderDetails() { protected ProviderDetails() {
@ -143,12 +143,12 @@ public class ClientRegistration {
this.tokenUri = tokenUri; this.tokenUri = tokenUri;
} }
public String getUserInfoUri() { public UserInfoEndpoint getUserInfoEndpoint() {
return this.userInfoUri; return this.userInfoEndpoint;
} }
protected void setUserInfoUri(String userInfoUri) { protected void setUserInfoEndpoint(UserInfoEndpoint userInfoEndpoint) {
this.userInfoUri = userInfoUri; this.userInfoEndpoint = userInfoEndpoint;
} }
public String getJwkSetUri() { public String getJwkSetUri() {
@ -158,6 +158,30 @@ public class ClientRegistration {
protected void setJwkSetUri(String jwkSetUri) { protected void setJwkSetUri(String jwkSetUri) {
this.jwkSetUri = jwkSetUri; this.jwkSetUri = jwkSetUri;
} }
public class UserInfoEndpoint {
private String uri;
private String userNameAttributeName;
protected UserInfoEndpoint() {
}
public String getUri() {
return this.uri;
}
protected void setUri(String uri) {
this.uri = uri;
}
public String getUserNameAttributeName() {
return this.userNameAttributeName;
}
protected void setUserNameAttributeName(String userNameAttributeName) {
this.userNameAttributeName = userNameAttributeName;
}
}
} }
public static class Builder { public static class Builder {
@ -170,6 +194,7 @@ public class ClientRegistration {
protected String authorizationUri; protected String authorizationUri;
protected String tokenUri; protected String tokenUri;
protected String userInfoUri; protected String userInfoUri;
protected String userNameAttributeName;
protected String jwkSetUri; protected String jwkSetUri;
protected String clientName; protected String clientName;
protected String clientAlias; protected String clientAlias;
@ -190,6 +215,7 @@ public class ClientRegistration {
this.authorizationUri(clientRegistrationProperties.getAuthorizationUri()); this.authorizationUri(clientRegistrationProperties.getAuthorizationUri());
this.tokenUri(clientRegistrationProperties.getTokenUri()); this.tokenUri(clientRegistrationProperties.getTokenUri());
this.userInfoUri(clientRegistrationProperties.getUserInfoUri()); this.userInfoUri(clientRegistrationProperties.getUserInfoUri());
this.userNameAttributeName(clientRegistrationProperties.getUserNameAttributeName());
this.jwkSetUri(clientRegistrationProperties.getJwkSetUri()); this.jwkSetUri(clientRegistrationProperties.getJwkSetUri());
this.clientName(clientRegistrationProperties.getClientName()); this.clientName(clientRegistrationProperties.getClientName());
this.clientAlias(clientRegistrationProperties.getClientAlias()); this.clientAlias(clientRegistrationProperties.getClientAlias());
@ -206,7 +232,8 @@ public class ClientRegistration {
} }
this.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()); this.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri());
this.tokenUri(clientRegistration.getProviderDetails().getTokenUri()); this.tokenUri(clientRegistration.getProviderDetails().getTokenUri());
this.userInfoUri(clientRegistration.getProviderDetails().getUserInfoUri()); this.userInfoUri(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUri());
this.userNameAttributeName(clientRegistration.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName());
this.jwkSetUri(clientRegistration.getProviderDetails().getJwkSetUri()); this.jwkSetUri(clientRegistration.getProviderDetails().getJwkSetUri());
this.clientName(clientRegistration.getClientName()); this.clientName(clientRegistration.getClientName());
this.clientAlias(clientRegistration.getClientAlias()); this.clientAlias(clientRegistration.getClientAlias());
@ -255,6 +282,11 @@ public class ClientRegistration {
return this; return this;
} }
public Builder userNameAttributeName(String userNameAttributeName) {
this.userNameAttributeName = userNameAttributeName;
return this;
}
public Builder jwkSetUri(String jwkSetUri) { public Builder jwkSetUri(String jwkSetUri) {
this.jwkSetUri = jwkSetUri; this.jwkSetUri = jwkSetUri;
return this; return this;
@ -288,7 +320,8 @@ public class ClientRegistration {
ProviderDetails providerDetails = clientRegistration.new ProviderDetails(); ProviderDetails providerDetails = clientRegistration.new ProviderDetails();
providerDetails.setAuthorizationUri(this.authorizationUri); providerDetails.setAuthorizationUri(this.authorizationUri);
providerDetails.setTokenUri(this.tokenUri); providerDetails.setTokenUri(this.tokenUri);
providerDetails.setUserInfoUri(this.userInfoUri); providerDetails.getUserInfoEndpoint().setUri(this.userInfoUri);
providerDetails.getUserInfoEndpoint().setUserNameAttributeName(this.userNameAttributeName);
providerDetails.setJwkSetUri(this.jwkSetUri); providerDetails.setJwkSetUri(this.jwkSetUri);
clientRegistration.setProviderDetails(providerDetails); clientRegistration.setProviderDetails(providerDetails);

View File

@ -42,6 +42,7 @@ public class ClientRegistrationProperties {
private String authorizationUri; private String authorizationUri;
private String tokenUri; private String tokenUri;
private String userInfoUri; private String userInfoUri;
private String userNameAttributeName;
private String jwkSetUri; private String jwkSetUri;
private String clientName; private String clientName;
private String clientAlias; private String clientAlias;
@ -119,6 +120,14 @@ public class ClientRegistrationProperties {
this.userInfoUri = userInfoUri; this.userInfoUri = userInfoUri;
} }
public String getUserNameAttributeName() {
return this.userNameAttributeName;
}
public void setUserNameAttributeName(String userNameAttributeName) {
this.userNameAttributeName = userNameAttributeName;
}
public String getJwkSetUri() { public String getJwkSetUri() {
return this.jwkSetUri; return this.jwkSetUri;
} }

View File

@ -56,7 +56,7 @@ public class CustomUserTypesOAuth2UserService implements OAuth2UserService {
@Override @Override
public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException { public OAuth2User loadUser(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
URI userInfoUri = URI.create(clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoUri()); URI userInfoUri = URI.create(clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
Class<? extends OAuth2User> customUserType; Class<? extends OAuth2User> customUserType;
if ((customUserType = this.getCustomUserTypes().get(userInfoUri)) == null) { if ((customUserType = this.getCustomUserTypes().get(userInfoUri)) == null) {
return null; return null;

View File

@ -66,7 +66,7 @@ public class DefaultOAuth2UserService implements OAuth2UserService {
return null; return null;
} }
URI userInfoUri = URI.create(clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoUri()); URI userInfoUri = URI.create(clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
if (!this.getUserNameAttributeNames().containsKey(userInfoUri)) { if (!this.getUserNameAttributeNames().containsKey(userInfoUri)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Missing required \"user name\" attribute name for UserInfo Endpoint: " + userInfoUri.toString()); "Missing required \"user name\" attribute name for UserInfo Endpoint: " + userInfoUri.toString());

View File

@ -48,7 +48,7 @@ public class NimbusUserInfoRetriever implements UserInfoRetriever {
@Override @Override
public Map<String, Object> retrieve(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException { public Map<String, Object> retrieve(OAuth2ClientAuthenticationToken clientAuthentication) throws OAuth2AuthenticationException {
URI userInfoUri = URI.create(clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoUri()); URI userInfoUri = URI.create(clientAuthentication.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
BearerAccessToken accessToken = new BearerAccessToken(clientAuthentication.getAccessToken().getTokenValue()); BearerAccessToken accessToken = new BearerAccessToken(clientAuthentication.getAccessToken().getTokenValue());
UserInfoRequest userInfoRequest = new UserInfoRequest(userInfoUri, accessToken); UserInfoRequest userInfoRequest = new UserInfoRequest(userInfoUri, accessToken);

View File

@ -23,19 +23,12 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration; import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import java.net.URI;
import java.util.Set;
import static org.springframework.boot.autoconfigure.security.oauth2.client.ClientRegistrationAutoConfiguration.*;
/** /**
* @author Joe Grandja * @author Joe Grandja
*/ */
@ -47,44 +40,19 @@ import static org.springframework.boot.autoconfigure.security.oauth2.client.Clie
@AutoConfigureBefore(SecurityAutoConfiguration.class) @AutoConfigureBefore(SecurityAutoConfiguration.class)
@AutoConfigureAfter(ClientRegistrationAutoConfiguration.class) @AutoConfigureAfter(ClientRegistrationAutoConfiguration.class)
public class OAuth2LoginAutoConfiguration { public class OAuth2LoginAutoConfiguration {
private static final String USER_INFO_URI_PROPERTY = "user-info-uri";
private static final String USER_NAME_ATTR_NAME_PROPERTY = "user-name-attribute-name";
@EnableWebSecurity @EnableWebSecurity
protected static class OAuth2LoginSecurityConfiguration extends WebSecurityConfigurerAdapter { protected static class OAuth2LoginSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final Environment environment;
protected OAuth2LoginSecurityConfiguration(Environment environment) {
this.environment = environment;
}
// @formatter:off // @formatter:off
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http http
.authorizeRequests() .authorizeRequests()
.antMatchers("/favicon.ico").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
.and() .and()
.oauth2Login(); .oauth2Login();
this.registerUserNameAttributeNames(http.oauth2Login());
} }
// @formatter:on // @formatter:on
private void registerUserNameAttributeNames(OAuth2LoginConfigurer<HttpSecurity> oauth2LoginConfigurer) throws Exception {
Set<String> clientPropertyKeys = resolveClientPropertyKeys(this.environment);
for (String clientPropertyKey : clientPropertyKeys) {
String fullClientPropertyKey = CLIENT_PROPERTY_PREFIX + "." + clientPropertyKey;
if (!this.environment.containsProperty(fullClientPropertyKey + "." + CLIENT_ID_PROPERTY)) {
continue;
}
String userInfoUriValue = this.environment.getProperty(fullClientPropertyKey + "." + USER_INFO_URI_PROPERTY);
String userNameAttributeNameValue = this.environment.getProperty(fullClientPropertyKey + "." + USER_NAME_ATTR_NAME_PROPERTY);
if (userInfoUriValue != null && userNameAttributeNameValue != null) {
oauth2LoginConfigurer.userInfoEndpoint().userNameAttributeName(userNameAttributeNameValue, URI.create(userInfoUriValue));
}
}
}
} }
} }

View File

@ -49,7 +49,7 @@ public class MainController {
Map userAttributes = this.webClient Map userAttributes = this.webClient
.filter(oauth2Credentials(authentication)) .filter(oauth2Credentials(authentication))
.get() .get()
.uri(authentication.getClientAuthentication().getClientRegistration().getProviderDetails().getUserInfoUri()) .uri(authentication.getClientAuthentication().getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri())
.retrieve() .retrieve()
.bodyToMono(Map.class) .bodyToMono(Map.class)
.block(); .block();