diff --git a/sdk/spring/CHANGELOG.md b/sdk/spring/CHANGELOG.md index b5bc1f4cd39e..cbaa1bc24848 100644 --- a/sdk/spring/CHANGELOG.md +++ b/sdk/spring/CHANGELOG.md @@ -1,8 +1,13 @@ # Release History ## 4.5.0-beta.2 (Unreleased) + Upgrade Spring Boot dependencies version to 2.7.4 and Spring Cloud dependencies version to 2021.0.4 +### Bugs Fixed + - Fix bug: The parameter 'scope' is duplicated. [31191](https://github.com/Azure/azure-sdk-for-java/issues/31191). + + ## 4.4.0 (2022-09-26) Upgrade Spring Boot dependencies version to 2.7.3 and Spring Cloud dependencies version to 2021.0.3 Upgrade Spring Boot dependencies version to 2.7.2 and Spring Cloud dependencies version to 2021.0.3. diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/configuration/AadOAuth2ClientConfiguration.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/configuration/AadOAuth2ClientConfiguration.java index a6d8369d2253..3b0a7f652478 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/configuration/AadOAuth2ClientConfiguration.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/configuration/AadOAuth2ClientConfiguration.java @@ -142,13 +142,13 @@ JwtBearerOAuth2AuthorizedClientProvider azureAdJwtBearerProvider( ObjectProvider resolvers) { JwtBearerOAuth2AuthorizedClientProvider provider = new JwtBearerOAuth2AuthorizedClientProvider(); OAuth2ClientAuthenticationJwkResolver resolver = resolvers.getIfUnique(); - AadJwtBearerGrantRequestEntityConverter jwtBearerConverter = new AadJwtBearerGrantRequestEntityConverter(); - if (resolver != null) { - jwtBearerConverter.addParametersConverter(new AadJwtClientAuthenticationParametersConverter<>(resolver::resolve)); - } DefaultJwtBearerTokenResponseClient responseClient = new DefaultJwtBearerTokenResponseClient(); responseClient.setRestOperations(createOAuth2AccessTokenResponseClientRestTemplate(restTemplateBuilder)); - responseClient.setRequestEntityConverter(jwtBearerConverter); + AadJwtBearerGrantRequestEntityConverter converter = new AadJwtBearerGrantRequestEntityConverter(); + if (resolver != null) { + converter.addParametersConverter(new AadJwtClientAuthenticationParametersConverter<>(resolver::resolve)); + } + responseClient.setRequestEntityConverter(converter); provider.setAccessTokenResponseClient(responseClient); return provider; } @@ -159,47 +159,42 @@ RefreshTokenOAuth2AuthorizedClientProvider azureRefreshTokenProvider( ObjectProvider resolvers) { RefreshTokenOAuth2AuthorizedClientProvider provider = new RefreshTokenOAuth2AuthorizedClientProvider(); OAuth2ClientAuthenticationJwkResolver resolver = resolvers.getIfUnique(); + DefaultRefreshTokenTokenResponseClient responseClient = new DefaultRefreshTokenTokenResponseClient(); + responseClient.setRestOperations(createOAuth2AccessTokenResponseClientRestTemplate(restTemplateBuilder)); if (resolver != null) { OAuth2RefreshTokenGrantRequestEntityConverter converter = new OAuth2RefreshTokenGrantRequestEntityConverter(); converter.addParametersConverter(new AadJwtClientAuthenticationParametersConverter<>(resolver::resolve)); - - DefaultRefreshTokenTokenResponseClient responseClient = new DefaultRefreshTokenTokenResponseClient(); - responseClient.setRestOperations(createOAuth2AccessTokenResponseClientRestTemplate(restTemplateBuilder)); responseClient.setRequestEntityConverter(converter); - provider.setAccessTokenResponseClient(responseClient); } + provider.setAccessTokenResponseClient(responseClient); return provider; } private void passwordGrantBuilderAccessTokenResponseClientCustomizer( OAuth2AuthorizedClientProviderBuilder.PasswordGrantBuilder builder, OAuth2ClientAuthenticationJwkResolver resolver) { + DefaultPasswordTokenResponseClient responseClient = new DefaultPasswordTokenResponseClient(); + responseClient.setRestOperations(createOAuth2AccessTokenResponseClientRestTemplate(restTemplateBuilder)); if (resolver != null) { OAuth2PasswordGrantRequestEntityConverter converter = new OAuth2PasswordGrantRequestEntityConverter(); converter.addParametersConverter(new AadJwtClientAuthenticationParametersConverter<>(resolver::resolve)); - - DefaultPasswordTokenResponseClient client = new DefaultPasswordTokenResponseClient(); - client.setRestOperations(createOAuth2AccessTokenResponseClientRestTemplate(restTemplateBuilder)); - client.setRequestEntityConverter(converter); - - builder.accessTokenResponseClient(client); + responseClient.setRequestEntityConverter(converter); } + builder.accessTokenResponseClient(responseClient); } private void clientCredentialsGrantBuilderAccessTokenResponseClientCustomizer( OAuth2AuthorizedClientProviderBuilder.ClientCredentialsGrantBuilder builder, OAuth2ClientAuthenticationJwkResolver resolver) { + DefaultClientCredentialsTokenResponseClient responseClient = new DefaultClientCredentialsTokenResponseClient(); + responseClient.setRestOperations(createOAuth2AccessTokenResponseClientRestTemplate(restTemplateBuilder)); if (resolver != null) { OAuth2ClientCredentialsGrantRequestEntityConverter converter = new OAuth2ClientCredentialsGrantRequestEntityConverter(); converter.addParametersConverter(new AadJwtClientAuthenticationParametersConverter<>(resolver::resolve)); - - DefaultClientCredentialsTokenResponseClient client = new DefaultClientCredentialsTokenResponseClient(); - client.setRestOperations(createOAuth2AccessTokenResponseClientRestTemplate(restTemplateBuilder)); - client.setRequestEntityConverter(converter); - - builder.accessTokenResponseClient(client); + responseClient.setRequestEntityConverter(converter); } + builder.accessTokenResponseClient(responseClient); } private AadAzureDelegatedOAuth2AuthorizedClientProvider azureDelegatedOAuth2AuthorizedClientProvider( diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/AadRestTemplateCreator.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/AadRestTemplateCreator.java index 6cf836892cba..314f9742f8e7 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/AadRestTemplateCreator.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/AadRestTemplateCreator.java @@ -5,14 +5,11 @@ import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.converter.FormHttpMessageConverter; -import org.springframework.http.converter.HttpMessageConverter; import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler; import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter; import org.springframework.util.Assert; import org.springframework.web.client.RestTemplate; -import java.util.List; - /** * Util class used to create {@link RestTemplate}s for all Azure AD related http requests. */ @@ -27,25 +24,14 @@ public static RestTemplate createRestTemplate(RestTemplateBuilder builder) { } public static RestTemplate createOAuth2ErrorResponseHandledRestTemplate(RestTemplateBuilder builder) { - RestTemplate restTemplate = createRestTemplate(builder); - restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler()); - return restTemplate; + builder = builder.errorHandler(new OAuth2ErrorResponseErrorHandler()); + return createRestTemplate(builder); } public static RestTemplate createOAuth2AccessTokenResponseClientRestTemplate(RestTemplateBuilder builder) { - RestTemplate restTemplate = createOAuth2ErrorResponseHandledRestTemplate(builder); - List> converters = restTemplate.getMessageConverters(); - if (notContainsElementOfType(converters, FormHttpMessageConverter.class)) { - converters.add(new FormHttpMessageConverter()); - } - if (notContainsElementOfType(converters, OAuth2AccessTokenResponseHttpMessageConverter.class)) { - converters.add(new OAuth2AccessTokenResponseHttpMessageConverter()); - } - return restTemplate; - } - - private static boolean notContainsElementOfType(List list, Class clazz) { - return list.stream().noneMatch(item -> item.getClass().equals(clazz)); + builder = builder.messageConverters( + new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter()); + return createOAuth2ErrorResponseHandledRestTemplate(builder); } } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/jackson/SerializerUtils.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/jackson/SerializerUtils.java index f5ba0fde806c..93c9bee6222e 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/jackson/SerializerUtils.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/jackson/SerializerUtils.java @@ -10,7 +10,7 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.jackson2.OAuth2ClientJackson2Module; -import java.util.HashMap; +import java.util.Collections; import java.util.Map; public final class SerializerUtils { @@ -45,7 +45,7 @@ public static String serializeOAuth2AuthorizedClientMap(Map deserializeOAuth2AuthorizedClientMap(String authorizedClientsString) { if (authorizedClientsString == null) { - return new HashMap<>(); + return Collections.emptyMap(); } Map authorizedClients; try { diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/oauth2/AbstractOAuth2AuthorizationCodeGrantRequestEntityConverter.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/oauth2/AbstractOAuth2AuthorizationCodeGrantRequestEntityConverter.java index af91381bb842..865f1ff1ca79 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/oauth2/AbstractOAuth2AuthorizationCodeGrantRequestEntityConverter.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/oauth2/AbstractOAuth2AuthorizationCodeGrantRequestEntityConverter.java @@ -4,11 +4,10 @@ package com.azure.spring.cloud.autoconfigure.aad.implementation.oauth2; import com.azure.spring.cloud.core.implementation.util.AzureSpringIdentifier; -import org.springframework.core.convert.converter.Converter; import org.springframework.http.HttpHeaders; -import org.springframework.http.RequestEntity; import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequestEntityConverter; +import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import java.util.Collections; @@ -20,25 +19,17 @@ public abstract class AbstractOAuth2AuthorizationCodeGrantRequestEntityConverter extends OAuth2AuthorizationCodeGrantRequestEntityConverter { + protected AbstractOAuth2AuthorizationCodeGrantRequestEntityConverter() { + addHeadersConverter((request) -> getHttpHeaders()); + addParametersConverter(this::getHttpBody); + } + /** * Gets the application ID. * * @return the application ID */ protected abstract String getApplicationId(); - - @Override - @SuppressWarnings("unchecked") - public RequestEntity convert(OAuth2AuthorizationCodeGrantRequest request) { - addHeadersConverter(headersConverter); - addParametersConverter(parametersConverter); - return super.convert(request); - } - - private final Converter headersConverter = (request) -> getHttpHeaders(); - - private final Converter> parametersConverter = this::getHttpBody; - /** * Additional default headers information. * @return HttpHeaders @@ -57,6 +48,6 @@ public HttpHeaders getHttpHeaders() { * @return MultiValueMap */ public MultiValueMap getHttpBody(OAuth2AuthorizationCodeGrantRequest request) { - return null; + return new LinkedMultiValueMap<>(); } } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/oauth2/JacksonHttpSessionOAuth2AuthorizedClientRepository.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/oauth2/JacksonHttpSessionOAuth2AuthorizedClientRepository.java index 4516ec6e1151..2729f103d419 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/oauth2/JacksonHttpSessionOAuth2AuthorizedClientRepository.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/aad/implementation/oauth2/JacksonHttpSessionOAuth2AuthorizedClientRepository.java @@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -48,10 +49,10 @@ public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authen Assert.notNull(authorizedClient, "authorizedClient cannot be null"); Assert.notNull(request, MSG_REQUEST_CANNOT_BE_NULL); Assert.notNull(response, "response cannot be null"); - Map authorizedClients = this.getAuthorizedClients(request); + Map authorizedClients = new HashMap<>(this.getAuthorizedClients(request)); authorizedClients.put(authorizedClient.getClientRegistration().getRegistrationId(), authorizedClient); request.getSession().setAttribute(AUTHORIZED_CLIENTS_ATTR_NAME, - serializeOAuth2AuthorizedClientMap(authorizedClients)); + serializeOAuth2AuthorizedClientMap(Collections.unmodifiableMap(authorizedClients))); } @Override @@ -77,6 +78,6 @@ private Map getAuthorizedClients(HttpServletRequ .map(s -> s.getAttribute(AUTHORIZED_CLIENTS_ATTR_NAME)) .map(Object::toString) .map(SerializerUtils::deserializeOAuth2AuthorizedClientMap) - .orElse(Collections.emptyMap()); + .orElseGet(Collections::emptyMap); } } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/aad/implementation/AadRestTemplateCreatorTest.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/aad/implementation/AadRestTemplateCreatorTest.java index 054a22267433..5bc4219b9112 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/aad/implementation/AadRestTemplateCreatorTest.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/aad/implementation/AadRestTemplateCreatorTest.java @@ -43,22 +43,23 @@ void testAadRestOperationConfiguration() { RestTemplate restTemplate = createRestTemplate(builder); ResponseErrorHandler handler = restTemplate.getErrorHandler(); - assertNotEquals(handler.getClass(), OAuth2ErrorResponseErrorHandler.class); + assertNotEquals(OAuth2ErrorResponseErrorHandler.class, handler.getClass()); List> converters = restTemplate.getMessageConverters(); assertFalse(hasItemOfClass(converters, FormHttpMessageConverter.class)); assertFalse(hasItemOfClass(converters, OAuth2AccessTokenResponseHttpMessageConverter.class)); restTemplate = createOAuth2ErrorResponseHandledRestTemplate(builder); handler = restTemplate.getErrorHandler(); - assertEquals(handler.getClass(), OAuth2ErrorResponseErrorHandler.class); + assertEquals(OAuth2ErrorResponseErrorHandler.class, handler.getClass()); converters = restTemplate.getMessageConverters(); assertFalse(hasItemOfClass(converters, FormHttpMessageConverter.class)); assertFalse(hasItemOfClass(converters, OAuth2AccessTokenResponseHttpMessageConverter.class)); restTemplate = createOAuth2AccessTokenResponseClientRestTemplate(builder); handler = restTemplate.getErrorHandler(); - assertEquals(handler.getClass(), OAuth2ErrorResponseErrorHandler.class); + assertEquals(OAuth2ErrorResponseErrorHandler.class, handler.getClass()); converters = restTemplate.getMessageConverters(); + assertEquals(2, converters.size()); assertTrue(hasItemOfClass(converters, FormHttpMessageConverter.class)); assertTrue(hasItemOfClass(converters, OAuth2AccessTokenResponseHttpMessageConverter.class)); });