Remove deprecated CustomUserTypesOAuth2UserService
Closes gh-11511
This commit is contained in:
parent
67b27a41c3
commit
42683693c0
|
@ -17,11 +17,9 @@
|
||||||
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
|
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||||
|
@ -48,9 +46,7 @@ import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
|
||||||
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
|
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||||
import org.springframework.security.oauth2.client.userinfo.CustomUserTypesOAuth2UserService;
|
|
||||||
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
|
||||||
import org.springframework.security.oauth2.client.userinfo.DelegatingOAuth2UserService;
|
|
||||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
|
||||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
||||||
import org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository;
|
import org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository;
|
||||||
|
@ -438,16 +434,7 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||||
ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OAuth2UserRequest.class,
|
ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OAuth2UserRequest.class,
|
||||||
OAuth2User.class);
|
OAuth2User.class);
|
||||||
OAuth2UserService<OAuth2UserRequest, OAuth2User> bean = getBeanOrNull(type);
|
OAuth2UserService<OAuth2UserRequest, OAuth2User> bean = getBeanOrNull(type);
|
||||||
if (bean != null) {
|
return (bean != null) ? bean : new DefaultOAuth2UserService();
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
if (this.userInfoEndpointConfig.customUserTypes.isEmpty()) {
|
|
||||||
return new DefaultOAuth2UserService();
|
|
||||||
}
|
|
||||||
List<OAuth2UserService<OAuth2UserRequest, OAuth2User>> userServices = new ArrayList<>();
|
|
||||||
userServices.add(new CustomUserTypesOAuth2UserService(this.userInfoEndpointConfig.customUserTypes));
|
|
||||||
userServices.add(new DefaultOAuth2UserService());
|
|
||||||
return new DelegatingOAuth2UserService<>(userServices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T getBeanOrNull(ResolvableType type) {
|
private <T> T getBeanOrNull(ResolvableType type) {
|
||||||
|
@ -666,8 +653,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||||
|
|
||||||
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;
|
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;
|
||||||
|
|
||||||
private Map<String, Class<? extends OAuth2User>> customUserTypes = new HashMap<>();
|
|
||||||
|
|
||||||
private UserInfoEndpointConfig() {
|
private UserInfoEndpointConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -697,23 +682,6 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a custom {@link OAuth2User} type and associates it to the provided client
|
|
||||||
* {@link ClientRegistration#getRegistrationId() registration identifier}.
|
|
||||||
* @param customUserType a custom {@link OAuth2User} type
|
|
||||||
* @param clientRegistrationId the client registration identifier
|
|
||||||
* @return the {@link UserInfoEndpointConfig} for further configuration
|
|
||||||
* @deprecated See {@link CustomUserTypesOAuth2UserService} for alternative usage.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public UserInfoEndpointConfig customUserType(Class<? extends OAuth2User> customUserType,
|
|
||||||
String clientRegistrationId) {
|
|
||||||
Assert.notNull(customUserType, "customUserType cannot be null");
|
|
||||||
Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty");
|
|
||||||
this.customUserTypes.put(clientRegistrationId, customUserType);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link GrantedAuthoritiesMapper} used for mapping
|
* Sets the {@link GrantedAuthoritiesMapper} used for mapping
|
||||||
* {@link OAuth2User#getAuthorities()}.
|
* {@link OAuth2User#getAuthorities()}.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2021 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -20,7 +20,6 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer
|
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer
|
||||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper
|
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper
|
||||||
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest
|
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration
|
|
||||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest
|
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest
|
||||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService
|
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService
|
||||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser
|
import org.springframework.security.oauth2.core.oidc.user.OidcUser
|
||||||
|
@ -44,39 +43,11 @@ class UserInfoEndpointDsl {
|
||||||
var oidcUserService: OAuth2UserService<OidcUserRequest, OidcUser>? = null
|
var oidcUserService: OAuth2UserService<OidcUserRequest, OidcUser>? = null
|
||||||
var userAuthoritiesMapper: GrantedAuthoritiesMapper? = null
|
var userAuthoritiesMapper: GrantedAuthoritiesMapper? = null
|
||||||
|
|
||||||
private var customUserTypePair: Pair<Class<out OAuth2User>, String>? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a custom [OAuth2User] type and associates it to the provided
|
|
||||||
* client [ClientRegistration.getRegistrationId] registration identifier.
|
|
||||||
*
|
|
||||||
* @param customUserType a custom [OAuth2User] type
|
|
||||||
* @param clientRegistrationId the client registration identifier
|
|
||||||
*/
|
|
||||||
@Deprecated("Use 'customUserType<T>(clientRegistrationId)' instead.")
|
|
||||||
fun customUserType(customUserType: Class<out OAuth2User>, clientRegistrationId: String) {
|
|
||||||
customUserTypePair = Pair(customUserType, clientRegistrationId)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a custom [OAuth2User] type and associates it to the provided
|
|
||||||
* client [ClientRegistration.getRegistrationId] registration identifier.
|
|
||||||
* Variant that is leveraging Kotlin reified type parameters.
|
|
||||||
*
|
|
||||||
* @param T a custom [OAuth2User] type
|
|
||||||
* @param clientRegistrationId the client registration identifier
|
|
||||||
*/
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
inline fun <reified T: OAuth2User> customUserType(clientRegistrationId: String) {
|
|
||||||
customUserType(T::class.java, clientRegistrationId)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun get(): (OAuth2LoginConfigurer<HttpSecurity>.UserInfoEndpointConfig) -> Unit {
|
internal fun get(): (OAuth2LoginConfigurer<HttpSecurity>.UserInfoEndpointConfig) -> Unit {
|
||||||
return { userInfoEndpoint ->
|
return { userInfoEndpoint ->
|
||||||
userService?.also { userInfoEndpoint.userService(userService) }
|
userService?.also { userInfoEndpoint.userService(userService) }
|
||||||
oidcUserService?.also { userInfoEndpoint.oidcUserService(oidcUserService) }
|
oidcUserService?.also { userInfoEndpoint.oidcUserService(oidcUserService) }
|
||||||
userAuthoritiesMapper?.also { userInfoEndpoint.userAuthoritiesMapper(userAuthoritiesMapper) }
|
userAuthoritiesMapper?.also { userInfoEndpoint.userAuthoritiesMapper(userAuthoritiesMapper) }
|
||||||
customUserTypePair?.also { userInfoEndpoint.customUserType(customUserTypePair!!.first, customUserTypePair!!.second) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-2020 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.security.oauth2.client.userinfo;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
|
||||||
import org.springframework.http.RequestEntity;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
|
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
|
||||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
|
||||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.web.client.ResponseErrorHandler;
|
|
||||||
import org.springframework.web.client.RestClientException;
|
|
||||||
import org.springframework.web.client.RestOperations;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of an {@link OAuth2UserService} that supports custom
|
|
||||||
* {@link OAuth2User} types.
|
|
||||||
* <p>
|
|
||||||
* The custom user type(s) is supplied via the constructor, using a {@code Map} of
|
|
||||||
* {@link OAuth2User} type(s) keyed by {@code String}, which represents the
|
|
||||||
* {@link ClientRegistration#getRegistrationId() Registration Id} of the Client.
|
|
||||||
*
|
|
||||||
* @author Joe Grandja
|
|
||||||
* @since 5.0
|
|
||||||
* @see OAuth2UserService
|
|
||||||
* @see OAuth2UserRequest
|
|
||||||
* @see OAuth2User
|
|
||||||
* @see ClientRegistration
|
|
||||||
* @deprecated It is recommended to use a delegation-based strategy of an
|
|
||||||
* {@link OAuth2UserService} to support custom {@link OAuth2User} types, as it provides
|
|
||||||
* much greater flexibility compared to this implementation. See the
|
|
||||||
* <a target="_blank" href=
|
|
||||||
* "https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login-advanced-map-authorities-oauth2userservice">reference
|
|
||||||
* manual</a> for details on how to implement.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class CustomUserTypesOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
|
|
||||||
|
|
||||||
private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response";
|
|
||||||
|
|
||||||
private final Map<String, Class<? extends OAuth2User>> customUserTypes;
|
|
||||||
|
|
||||||
private Converter<OAuth2UserRequest, RequestEntity<?>> requestEntityConverter = new OAuth2UserRequestEntityConverter();
|
|
||||||
|
|
||||||
private RestOperations restOperations;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a {@code CustomUserTypesOAuth2UserService} using the provided
|
|
||||||
* parameters.
|
|
||||||
* @param customUserTypes a {@code Map} of {@link OAuth2User} type(s) keyed by
|
|
||||||
* {@link ClientRegistration#getRegistrationId() Registration Id}
|
|
||||||
*/
|
|
||||||
public CustomUserTypesOAuth2UserService(Map<String, Class<? extends OAuth2User>> customUserTypes) {
|
|
||||||
Assert.notEmpty(customUserTypes, "customUserTypes cannot be empty");
|
|
||||||
this.customUserTypes = Collections.unmodifiableMap(new LinkedHashMap<>(customUserTypes));
|
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
|
||||||
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
|
|
||||||
this.restOperations = restTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
|
|
||||||
Assert.notNull(userRequest, "userRequest cannot be null");
|
|
||||||
String registrationId = userRequest.getClientRegistration().getRegistrationId();
|
|
||||||
Class<? extends OAuth2User> customUserType = this.customUserTypes.get(registrationId);
|
|
||||||
if (customUserType == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
RequestEntity<?> request = this.requestEntityConverter.convert(userRequest);
|
|
||||||
ResponseEntity<? extends OAuth2User> response = getResponse(customUserType, request);
|
|
||||||
OAuth2User oauth2User = response.getBody();
|
|
||||||
return oauth2User;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResponseEntity<? extends OAuth2User> getResponse(Class<? extends OAuth2User> customUserType,
|
|
||||||
RequestEntity<?> request) {
|
|
||||||
try {
|
|
||||||
return this.restOperations.exchange(request, customUserType);
|
|
||||||
}
|
|
||||||
catch (RestClientException ex) {
|
|
||||||
OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE,
|
|
||||||
"An error occurred while attempting to retrieve the UserInfo Resource: " + ex.getMessage(), null);
|
|
||||||
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@link Converter} used for converting the {@link OAuth2UserRequest} to a
|
|
||||||
* {@link RequestEntity} representation of the UserInfo Request.
|
|
||||||
* @param requestEntityConverter the {@link Converter} used for converting to a
|
|
||||||
* {@link RequestEntity} representation of the UserInfo Request
|
|
||||||
* @since 5.1
|
|
||||||
*/
|
|
||||||
public final void setRequestEntityConverter(Converter<OAuth2UserRequest, RequestEntity<?>> requestEntityConverter) {
|
|
||||||
Assert.notNull(requestEntityConverter, "requestEntityConverter cannot be null");
|
|
||||||
this.requestEntityConverter = requestEntityConverter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@link RestOperations} used when requesting the UserInfo resource.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* <b>NOTE:</b> At a minimum, the supplied {@code restOperations} must be configured
|
|
||||||
* with the following:
|
|
||||||
* <ol>
|
|
||||||
* <li>{@link ResponseErrorHandler} - {@link OAuth2ErrorResponseErrorHandler}</li>
|
|
||||||
* </ol>
|
|
||||||
* @param restOperations the {@link RestOperations} used when requesting the UserInfo
|
|
||||||
* resource
|
|
||||||
* @since 5.1
|
|
||||||
*/
|
|
||||||
public final void setRestOperations(RestOperations restOperations) {
|
|
||||||
Assert.notNull(restOperations, "restOperations cannot be null");
|
|
||||||
this.restOperations = restOperations;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,266 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-2019 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.security.oauth2.client.userinfo;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import okhttp3.mockwebserver.MockResponse;
|
|
||||||
import okhttp3.mockwebserver.MockWebServer;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
|
||||||
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
|
|
||||||
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.TestOAuth2AccessTokens;
|
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link CustomUserTypesOAuth2UserService}.
|
|
||||||
*
|
|
||||||
* @author Joe Grandja
|
|
||||||
* @author Eddú Meléndez
|
|
||||||
*/
|
|
||||||
public class CustomUserTypesOAuth2UserServiceTests {
|
|
||||||
|
|
||||||
private ClientRegistration.Builder clientRegistrationBuilder;
|
|
||||||
|
|
||||||
private OAuth2AccessToken accessToken;
|
|
||||||
|
|
||||||
private CustomUserTypesOAuth2UserService userService;
|
|
||||||
|
|
||||||
private MockWebServer server;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
this.server = new MockWebServer();
|
|
||||||
this.server.start();
|
|
||||||
String registrationId = "client-registration-id-1";
|
|
||||||
// @formatter:off
|
|
||||||
this.clientRegistrationBuilder = TestClientRegistrations.clientRegistration()
|
|
||||||
.registrationId(registrationId);
|
|
||||||
// @formatter:on
|
|
||||||
this.accessToken = TestOAuth2AccessTokens.noScopes();
|
|
||||||
Map<String, Class<? extends OAuth2User>> customUserTypes = new HashMap<>();
|
|
||||||
customUserTypes.put(registrationId, CustomOAuth2User.class);
|
|
||||||
this.userService = new CustomUserTypesOAuth2UserService(customUserTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
public void cleanup() throws Exception {
|
|
||||||
this.server.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void constructorWhenCustomUserTypesIsNullThenThrowIllegalArgumentException() {
|
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> new CustomUserTypesOAuth2UserService(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void constructorWhenCustomUserTypesIsEmptyThenThrowIllegalArgumentException() {
|
|
||||||
assertThatIllegalArgumentException()
|
|
||||||
.isThrownBy(() -> new CustomUserTypesOAuth2UserService(Collections.emptyMap()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void setRequestEntityConverterWhenNullThenThrowIllegalArgumentException() {
|
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> this.userService.setRequestEntityConverter(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void setRestOperationsWhenNullThenThrowIllegalArgumentException() {
|
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> this.userService.setRestOperations(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void loadUserWhenUserRequestIsNullThenThrowIllegalArgumentException() {
|
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> this.userService.loadUser(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void loadUserWhenCustomUserTypeNotFoundThenReturnNull() {
|
|
||||||
// @formatter:off
|
|
||||||
ClientRegistration clientRegistration = TestClientRegistrations.clientRegistration()
|
|
||||||
.registrationId("other-client-registration-id-1")
|
|
||||||
.build();
|
|
||||||
// @formatter:on
|
|
||||||
OAuth2User user = this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken));
|
|
||||||
assertThat(user).isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void loadUserWhenUserInfoSuccessResponseThenReturnUser() {
|
|
||||||
// @formatter:off
|
|
||||||
String userInfoResponse = "{\n"
|
|
||||||
+ " \"id\": \"12345\",\n"
|
|
||||||
+ " \"name\": \"first last\",\n"
|
|
||||||
+ " \"login\": \"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();
|
|
||||||
OAuth2User user = this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken));
|
|
||||||
assertThat(user.getName()).isEqualTo("first last");
|
|
||||||
assertThat(user.getAttributes().size()).isEqualTo(4);
|
|
||||||
assertThat((String) user.getAttribute("id")).isEqualTo("12345");
|
|
||||||
assertThat((String) user.getAttribute("name")).isEqualTo("first last");
|
|
||||||
assertThat((String) user.getAttribute("login")).isEqualTo("user1");
|
|
||||||
assertThat((String) user.getAttribute("email")).isEqualTo("user1@example.com");
|
|
||||||
assertThat(user.getAuthorities().size()).isEqualTo(1);
|
|
||||||
assertThat(user.getAuthorities().iterator().next().getAuthority()).isEqualTo("ROLE_USER");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void loadUserWhenUserInfoSuccessResponseInvalidThenThrowOAuth2AuthenticationException() {
|
|
||||||
// @formatter:off
|
|
||||||
String userInfoResponse = "{\n"
|
|
||||||
+ " \"id\": \"12345\",\n"
|
|
||||||
+ " \"name\": \"first last\",\n"
|
|
||||||
|
|
||||||
+ " \"login\": \"user1\",\n"
|
|
||||||
+ " \"email\": \"user1@example.com\"\n";
|
|
||||||
// "}\n"; // Make the JSON invalid/malformed
|
|
||||||
// @formatter:on
|
|
||||||
this.server.enqueue(jsonResponse(userInfoResponse));
|
|
||||||
String userInfoUri = this.server.url("/user").toString();
|
|
||||||
ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build();
|
|
||||||
assertThatExceptionOfType(OAuth2AuthenticationException.class)
|
|
||||||
.isThrownBy(
|
|
||||||
() -> this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)))
|
|
||||||
.withMessageContaining(
|
|
||||||
"[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void loadUserWhenServerErrorThenThrowOAuth2AuthenticationException() {
|
|
||||||
this.server.enqueue(new MockResponse().setResponseCode(500));
|
|
||||||
String userInfoUri = this.server.url("/user").toString();
|
|
||||||
ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build();
|
|
||||||
assertThatExceptionOfType(OAuth2AuthenticationException.class)
|
|
||||||
.isThrownBy(
|
|
||||||
() -> this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)))
|
|
||||||
.withMessageContaining(
|
|
||||||
"[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 500 Server Error");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void loadUserWhenUserInfoUriInvalidThenThrowOAuth2AuthenticationException() {
|
|
||||||
String userInfoUri = "https://invalid-provider.com/user";
|
|
||||||
ClientRegistration clientRegistration = this.clientRegistrationBuilder.userInfoUri(userInfoUri).build();
|
|
||||||
assertThatExceptionOfType(OAuth2AuthenticationException.class)
|
|
||||||
.isThrownBy(
|
|
||||||
() -> this.userService.loadUser(new OAuth2UserRequest(clientRegistration, this.accessToken)))
|
|
||||||
.withMessageContaining(
|
|
||||||
"[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource");
|
|
||||||
}
|
|
||||||
|
|
||||||
private ClientRegistration.Builder withRegistrationId(String registrationId) {
|
|
||||||
// @formatter:off
|
|
||||||
return ClientRegistration.withRegistrationId(registrationId)
|
|
||||||
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
|
|
||||||
.clientId("client")
|
|
||||||
.tokenUri("/token");
|
|
||||||
// @formatter:on
|
|
||||||
}
|
|
||||||
|
|
||||||
private MockResponse jsonResponse(String json) {
|
|
||||||
return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class CustomOAuth2User implements OAuth2User {
|
|
||||||
|
|
||||||
private List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
|
|
||||||
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
private String login;
|
|
||||||
|
|
||||||
private String email;
|
|
||||||
|
|
||||||
public CustomOAuth2User() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
|
||||||
return this.authorities;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> getAttributes() {
|
|
||||||
Map<String, Object> attributes = new HashMap<>();
|
|
||||||
attributes.put("id", this.getId());
|
|
||||||
attributes.put("name", this.getName());
|
|
||||||
attributes.put("login", this.getLogin());
|
|
||||||
attributes.put("email", this.getEmail());
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLogin() {
|
|
||||||
return this.login;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLogin(String login) {
|
|
||||||
this.login = login;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmail() {
|
|
||||||
return this.email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmail(String email) {
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue