Remove setOidcUserMapper() in OidcUserService and OidcReactiveOAuth2UserService
Closes gh-18060
This commit is contained in:
-63
@@ -19,7 +19,6 @@ package org.springframework.security.oauth2.client.oidc.userinfo;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -27,23 +26,19 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.userinfo.DefaultReactiveOAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||
import org.springframework.security.oauth2.client.userinfo.ReactiveOAuth2UserService;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.converter.ClaimConversionService;
|
||||
import org.springframework.security.oauth2.core.converter.ClaimTypeConverter;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -171,64 +166,6 @@ public class OidcReactiveOAuth2UserService implements ReactiveOAuth2UserService<
|
||||
this.retrieveUserInfo = retrieveUserInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code BiFunction} used to map the {@link OidcUser user} from the
|
||||
* {@link OidcUserRequest user request} and {@link OidcUserInfo user info}.
|
||||
* <p>
|
||||
* This is useful when you need to map the user or authorities from the access token
|
||||
* itself. For example, when the authorization server provides authorization
|
||||
* information in the access token payload you can do the following: <pre>
|
||||
* @Bean
|
||||
* public OidcReactiveOAuth2UserService oidcUserService() {
|
||||
* var userService = new OidcReactiveOAuth2UserService();
|
||||
* userService.setOidcUserMapper(oidcUserMapper());
|
||||
* return userService;
|
||||
* }
|
||||
*
|
||||
* private static BiFunction<OidcUserRequest, OidcUserInfo, Mono<OidcUser>> oidcUserMapper() {
|
||||
* return (userRequest, userInfo) -> {
|
||||
* var accessToken = userRequest.getAccessToken();
|
||||
* var grantedAuthorities = new HashSet<GrantedAuthority>();
|
||||
* // TODO: Map authorities from the access token
|
||||
* var userNameAttributeName = "preferred_username";
|
||||
* return Mono.just(new DefaultOidcUser(
|
||||
* grantedAuthorities,
|
||||
* userRequest.getIdToken(),
|
||||
* userInfo,
|
||||
* userNameAttributeName
|
||||
* ));
|
||||
* };
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* Note that you can access the {@code userNameAttributeName} via the
|
||||
* {@link ClientRegistration} as follows: <pre>
|
||||
* var userNameAttributeName = userRequest.getClientRegistration()
|
||||
* .getProviderDetails()
|
||||
* .getUserInfoEndpoint()
|
||||
* .getUserNameAttributeName();
|
||||
* </pre>
|
||||
* <p>
|
||||
* By default, a {@link DefaultOidcUser} is created with authorities mapped as
|
||||
* follows:
|
||||
* <ul>
|
||||
* <li>An {@link OidcUserAuthority} is created from the {@link OidcIdToken} and
|
||||
* {@link OidcUserInfo} with an authority of {@code OIDC_USER}</li>
|
||||
* <li>Additional {@link SimpleGrantedAuthority authorities} are mapped from the
|
||||
* {@link OAuth2AccessToken#getScopes() access token scopes} with a prefix of
|
||||
* {@code SCOPE_}</li>
|
||||
* </ul>
|
||||
* @param oidcUserMapper the function used to map the {@link OidcUser} from the
|
||||
* {@link OidcUserRequest} and {@link OidcUserInfo}
|
||||
* @since 6.3
|
||||
* @deprecated Use {@link #setOidcUserConverter(Converter)} instead
|
||||
*/
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
public final void setOidcUserMapper(BiFunction<OidcUserRequest, OidcUserInfo, Mono<OidcUser>> oidcUserMapper) {
|
||||
Assert.notNull(oidcUserMapper, "oidcUserMapper cannot be null");
|
||||
this.oidcUserConverter = (source) -> oidcUserMapper.apply(source.getUserRequest(), source.getUserInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows converting from the {@link OidcUserSource} to and {@link OidcUser}.
|
||||
* @param oidcUserConverter the {@link Converter} to use. Cannot be null.
|
||||
|
||||
-63
@@ -19,29 +19,24 @@ package org.springframework.security.oauth2.client.oidc.userinfo;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.converter.ClaimConversionService;
|
||||
import org.springframework.security.oauth2.core.converter.ClaimTypeConverter;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -182,64 +177,6 @@ public class OidcUserService implements OAuth2UserService<OidcUserRequest, OidcU
|
||||
this.retrieveUserInfo = retrieveUserInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code BiFunction} used to map the {@link OidcUser user} from the
|
||||
* {@link OidcUserRequest user request} and {@link OidcUserInfo user info}.
|
||||
* <p>
|
||||
* This is useful when you need to map the user or authorities from the access token
|
||||
* itself. For example, when the authorization server provides authorization
|
||||
* information in the access token payload you can do the following: <pre>
|
||||
* @Bean
|
||||
* public OidcUserService oidcUserService() {
|
||||
* var userService = new OidcUserService();
|
||||
* userService.setOidcUserMapper(oidcUserMapper());
|
||||
* return userService;
|
||||
* }
|
||||
*
|
||||
* private static BiFunction<OidcUserRequest, OidcUserInfo, OidcUser> oidcUserMapper() {
|
||||
* return (userRequest, userInfo) -> {
|
||||
* var accessToken = userRequest.getAccessToken();
|
||||
* var grantedAuthorities = new HashSet<GrantedAuthority>();
|
||||
* // TODO: Map authorities from the access token
|
||||
* var userNameAttributeName = "preferred_username";
|
||||
* return new DefaultOidcUser(
|
||||
* grantedAuthorities,
|
||||
* userRequest.getIdToken(),
|
||||
* userInfo,
|
||||
* userNameAttributeName
|
||||
* );
|
||||
* };
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* Note that you can access the {@code userNameAttributeName} via the
|
||||
* {@link ClientRegistration} as follows: <pre>
|
||||
* var userNameAttributeName = userRequest.getClientRegistration()
|
||||
* .getProviderDetails()
|
||||
* .getUserInfoEndpoint()
|
||||
* .getUserNameAttributeName();
|
||||
* </pre>
|
||||
* <p>
|
||||
* By default, a {@link DefaultOidcUser} is created with authorities mapped as
|
||||
* follows:
|
||||
* <ul>
|
||||
* <li>An {@link OidcUserAuthority} is created from the {@link OidcIdToken} and
|
||||
* {@link OidcUserInfo} with an authority of {@code OIDC_USER}</li>
|
||||
* <li>Additional {@link SimpleGrantedAuthority authorities} are mapped from the
|
||||
* {@link OAuth2AccessToken#getScopes() access token scopes} with a prefix of
|
||||
* {@code SCOPE_}</li>
|
||||
* </ul>
|
||||
* @param oidcUserMapper the function used to map the {@link OidcUser} from the
|
||||
* {@link OidcUserRequest} and {@link OidcUserInfo}
|
||||
* @since 6.3
|
||||
* @deprecated Use {@link #setOidcUserConverter(Converter)} instead
|
||||
*/
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
public final void setOidcUserMapper(BiFunction<OidcUserRequest, OidcUserInfo, OidcUser> oidcUserMapper) {
|
||||
Assert.notNull(oidcUserMapper, "oidcUserMapper cannot be null");
|
||||
this.oidcUserConverter = (source) -> oidcUserMapper.apply(source.getUserRequest(), source.getUserInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows converting from the {@link OidcUserSource} to and {@link OidcUser}.
|
||||
* @param oidcUserConverter the {@link Converter} to use. Cannot be null.
|
||||
|
||||
-52
@@ -23,7 +23,6 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -55,7 +54,6 @@ import org.springframework.security.oauth2.core.TestOAuth2AccessTokens;
|
||||
import org.springframework.security.oauth2.core.converter.ClaimTypeConverter;
|
||||
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.TestOidcIdTokens;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
@@ -68,8 +66,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.ArgumentMatchers.same;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -225,54 +221,6 @@ public class OidcReactiveOAuth2UserServiceTests {
|
||||
verify(customRetrieveUserInfo).test(userRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenCustomOidcUserMapperSetThenUsed() {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(StandardClaimNames.SUB, "subject");
|
||||
attributes.put("user", "steve");
|
||||
OAuth2User oauth2User = new DefaultOAuth2User(AuthorityUtils.createAuthorityList("ROLE_USER"), attributes,
|
||||
"user");
|
||||
given(this.oauth2UserService.loadUser(any(OidcUserRequest.class))).willReturn(Mono.just(oauth2User));
|
||||
BiFunction<OidcUserRequest, OidcUserInfo, Mono<OidcUser>> customOidcUserMapper = mock(BiFunction.class);
|
||||
OidcUser actualUser = new DefaultOidcUser(AuthorityUtils.createAuthorityList("a", "b"), this.idToken,
|
||||
IdTokenClaimNames.SUB);
|
||||
given(customOidcUserMapper.apply(any(OidcUserRequest.class), any(OidcUserInfo.class)))
|
||||
.willReturn(Mono.just(actualUser));
|
||||
this.userService.setOidcUserMapper(customOidcUserMapper);
|
||||
OidcUserRequest userRequest = userRequest();
|
||||
OidcUser oidcUser = this.userService.loadUser(userRequest).block();
|
||||
assertThat(oidcUser).isNotNull();
|
||||
assertThat(oidcUser).isEqualTo(actualUser);
|
||||
ArgumentCaptor<OidcUserInfo> userInfoCaptor = ArgumentCaptor.forClass(OidcUserInfo.class);
|
||||
verify(customOidcUserMapper).apply(eq(userRequest), userInfoCaptor.capture());
|
||||
OidcUserInfo userInfo = userInfoCaptor.getValue();
|
||||
assertThat(userInfo.getSubject()).isEqualTo("subject");
|
||||
assertThat(userInfo.getClaimAsString("user")).isEqualTo("steve");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenCustomOidcUserMapperSetAndUserInfoNotRetrievedThenUsed() {
|
||||
// @formatter:off
|
||||
this.accessToken = new OAuth2AccessToken(
|
||||
this.accessToken.getTokenType(),
|
||||
this.accessToken.getTokenValue(),
|
||||
this.accessToken.getIssuedAt(),
|
||||
this.accessToken.getExpiresAt(),
|
||||
Collections.emptySet());
|
||||
// @formatter:on
|
||||
BiFunction<OidcUserRequest, OidcUserInfo, Mono<OidcUser>> customOidcUserMapper = mock(BiFunction.class);
|
||||
OidcUser actualUser = new DefaultOidcUser(AuthorityUtils.createAuthorityList("a", "b"), this.idToken,
|
||||
IdTokenClaimNames.SUB);
|
||||
given(customOidcUserMapper.apply(any(OidcUserRequest.class), isNull())).willReturn(Mono.just(actualUser));
|
||||
this.userService.setOidcUserMapper(customOidcUserMapper);
|
||||
this.userService.setRetrieveUserInfo((oidcUserRequest) -> false);
|
||||
OidcUserRequest userRequest = userRequest();
|
||||
OidcUser oidcUser = this.userService.loadUser(userRequest).block();
|
||||
assertThat(oidcUser).isNotNull();
|
||||
assertThat(oidcUser).isEqualTo(actualUser);
|
||||
verify(customOidcUserMapper).apply(eq(userRequest), isNull(OidcUserInfo.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenTokenContainsScopesThenIndividualScopeAuthorities() {
|
||||
OidcReactiveOAuth2UserService userService = new OidcReactiveOAuth2UserService();
|
||||
|
||||
-43
@@ -21,7 +21,6 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -53,7 +52,6 @@ import org.springframework.security.oauth2.core.converter.ClaimTypeConverter;
|
||||
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcScopes;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.TestOidcIdTokens;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
@@ -67,7 +65,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.same;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -138,15 +135,6 @@ public class OidcUserServiceTests {
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setOidcUserMapperWhenNullThenThrowIllegalArgumentException() {
|
||||
// @formatter:off
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.userService.setOidcUserMapper(null))
|
||||
.withMessage("oidcUserMapper cannot be null");
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setOidcUserConverterWhenNullThenThrowIllegalArgumentException() {
|
||||
// @formatter:off
|
||||
@@ -192,37 +180,6 @@ public class OidcUserServiceTests {
|
||||
assertThat(user.getUserInfo()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenCustomOidcUserMapperSetThenUsed() {
|
||||
// @formatter:off
|
||||
String userInfoResponse = "{\n"
|
||||
+ " \"sub\": \"subject1\",\n"
|
||||
+ " \"name\": \"first last\",\n"
|
||||
+ " \"given_name\": \"first\",\n"
|
||||
+ " \"family_name\": \"last\",\n"
|
||||
+ " \"preferred_username\": \"user1\",\n"
|
||||
+ " \"email\": \"user1@example.com\"\n"
|
||||
+ "}\n";
|
||||
// @formatter:on
|
||||
this.server.enqueue(jsonResponse(userInfoResponse));
|
||||
String userInfoUri = this.server.url("/user").toString();
|
||||
ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build();
|
||||
this.accessToken = TestOAuth2AccessTokens.noScopes();
|
||||
BiFunction<OidcUserRequest, OidcUserInfo, OidcUser> customOidcUserMapper = mock(BiFunction.class);
|
||||
OidcUser actualUser = new DefaultOidcUser(AuthorityUtils.createAuthorityList("a", "b"), this.idToken,
|
||||
IdTokenClaimNames.SUB);
|
||||
given(customOidcUserMapper.apply(any(OidcUserRequest.class), any(OidcUserInfo.class))).willReturn(actualUser);
|
||||
this.userService.setOidcUserMapper(customOidcUserMapper);
|
||||
OidcUserRequest userRequest = new OidcUserRequest(clientRegistration, this.accessToken, this.idToken);
|
||||
OidcUser user = this.userService.loadUser(userRequest);
|
||||
assertThat(user).isEqualTo(actualUser);
|
||||
ArgumentCaptor<OidcUserInfo> userInfoCaptor = ArgumentCaptor.forClass(OidcUserInfo.class);
|
||||
verify(customOidcUserMapper).apply(eq(userRequest), userInfoCaptor.capture());
|
||||
OidcUserInfo userInfo = userInfoCaptor.getValue();
|
||||
assertThat(userInfo.getSubject()).isEqualTo("subject1");
|
||||
assertThat(userInfo.getClaimAsString("preferred_username")).isEqualTo("user1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadUserWhenCustomOidcUserConverterSetThenUsed() {
|
||||
ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri("https://example.com/user")
|
||||
|
||||
Reference in New Issue
Block a user