From 12d6a840bfd297056f5b6a241ebad02f009ab13c Mon Sep 17 00:00:00 2001 From: prafsoni Date: Tue, 11 Nov 2025 00:03:40 -0800 Subject: [PATCH 1/5] feat: Add initial implementation for oauth2 support in the spring cloud config client Signed-off-by: prafsoni --- spring-cloud-config-client/pom.xml | 4 ++ .../config/client/ConfigClientProperties.java | 62 ++++++++++++++++- .../ConfigClientRequestTemplateFactory.java | 69 ++++++++++++++++++- 3 files changed, 132 insertions(+), 3 deletions(-) diff --git a/spring-cloud-config-client/pom.xml b/spring-cloud-config-client/pom.xml index 4d9d5095d1..7dc3275e8a 100644 --- a/spring-cloud-config-client/pom.xml +++ b/spring-cloud-config-client/pom.xml @@ -58,6 +58,10 @@ spring-boot-starter-actuator true + + org.springframework.boot + spring-boot-starter-security-oauth2-client + org.springframework.boot spring-boot-starter-aspectj diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientProperties.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientProperties.java index 28bfb3fd3b..816e60d2d6 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientProperties.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientProperties.java @@ -28,6 +28,7 @@ import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.security.oauth2.client.autoconfigure.OAuth2ClientProperties; import org.springframework.cloud.config.environment.EnvironmentMediaType; import org.springframework.cloud.configuration.TlsProperties; import org.springframework.core.env.Environment; @@ -185,6 +186,8 @@ public class ConfigClientProperties { */ private boolean sendAllLabels = false; + private OAuth2Properties oauth2 = new OAuth2Properties(); + ConfigClientProperties() { } @@ -352,6 +355,14 @@ public void setSendAllLabels(boolean sendAllLabels) { this.sendAllLabels = sendAllLabels; } + public OAuth2Properties getOauth2() { + return oauth2; + } + + public void setOauth2(OAuth2Properties oauth2) { + this.oauth2 = oauth2; + } + private Credentials extractCredentials(int index) { Credentials result = new Credentials(); int noOfUrl = this.uri.length; @@ -441,7 +452,8 @@ public String toString() { + Arrays.toString(this.uri) + ", mediaType=" + this.mediaType + ", discovery=" + this.discovery + ", failFast=" + this.failFast + ", token=" + this.token + ", requestConnectTimeout=" + this.requestConnectTimeout + ", requestReadTimeout=" + this.requestReadTimeout + ", sendState=" - + this.sendState + ", headers=" + this.headers + ", sendAllLabels=" + this.sendAllLabels + "]"; + + this.sendState + ", headers=" + this.headers + ", sendAllLabels=" + this.sendAllLabels + ", oauth2" + + this.oauth2 + "]"; } /** @@ -526,4 +538,52 @@ public enum MultipleUriStrategy { } + public static class OAuth2Properties { + + /** + * Default client registration id. + */ + public static final String CLIENT_REGISTRATION_ID = "config-oauth2-client"; + + /** + * Flag to say that the remote configuration server is configured with OAuth2. + * Default false.; + */ + private boolean enabled = false; + + private OAuth2ClientProperties.Provider provider = new OAuth2ClientProperties.Provider(); + + private OAuth2ClientProperties.Registration registration = new OAuth2ClientProperties.Registration(); + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public OAuth2ClientProperties.Provider getProvider() { + return provider; + } + + public void setProvider(OAuth2ClientProperties.Provider provider) { + this.provider = provider; + } + + public OAuth2ClientProperties.Registration getRegistration() { + return registration; + } + + public void setRegistration(OAuth2ClientProperties.Registration registration) { + this.registration = registration; + } + + @Override + public String toString() { + return "OAuth2Properties [" + "enabled=" + enabled + "]"; + } + + } + } diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactory.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactory.java index 6ceca390f0..b02437c96f 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactory.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactory.java @@ -18,9 +18,10 @@ import java.io.IOException; import java.security.GeneralSecurityException; -import java.util.Arrays; +import java.util.ArrayList; import java.util.Base64; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -35,6 +36,8 @@ import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.util.Timeout; +import org.springframework.boot.security.oauth2.client.autoconfigure.OAuth2ClientProperties; +import org.springframework.boot.security.oauth2.client.autoconfigure.OAuth2ClientPropertiesMapper; import org.springframework.cloud.configuration.SSLContextFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; @@ -44,6 +47,16 @@ import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.client.OAuth2ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; import static org.springframework.cloud.config.client.ConfigClientProperties.AUTHORIZATION; @@ -77,15 +90,67 @@ public RestTemplate create() { ClientHttpRequestFactory requestFactory = createHttpRequestFactory(properties); RestTemplate template = new RestTemplate(requestFactory); + + final List interceptors = new ArrayList<>(); Map headers = new HashMap<>(properties.getHeaders()); headers.remove(AUTHORIZATION); // To avoid redundant addition of header if (!headers.isEmpty()) { - template.setInterceptors(Arrays.asList(new GenericRequestHeaderInterceptor(headers))); + interceptors.add(new GenericRequestHeaderInterceptor(headers)); + } + + if (properties.getOauth2().isEnabled()) { + ClientHttpRequestInterceptor oauth2Interceptor = createOauth2Interceptor(properties.getOauth2()); + interceptors.add(oauth2Interceptor); } + template.setInterceptors(interceptors); return template; } + private ClientHttpRequestInterceptor createOauth2Interceptor(ConfigClientProperties.OAuth2Properties properties) { + final OAuth2AuthorizedClientManager authorizedClientManager = createAuthorizedClientManager(properties); + OAuth2ClientHttpRequestInterceptor oauth2Interceptor = new OAuth2ClientHttpRequestInterceptor( + authorizedClientManager); + oauth2Interceptor + .setClientRegistrationIdResolver(request -> ConfigClientProperties.OAuth2Properties.CLIENT_REGISTRATION_ID); + return oauth2Interceptor; + } + + private OAuth2AuthorizedClientManager createAuthorizedClientManager( + ConfigClientProperties.OAuth2Properties properties) { + + OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() + .clientCredentials() + .refreshToken() + .build(); + + ClientRegistrationRepository clientRegistrationRepository = clientRegistrationRepository(properties); + + OAuth2AuthorizedClientService authorizedClientService = new InMemoryOAuth2AuthorizedClientService( + clientRegistrationRepository); + + AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager( + clientRegistrationRepository, authorizedClientService); + authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); + return authorizedClientManager; + } + + private ClientRegistrationRepository clientRegistrationRepository( + ConfigClientProperties.OAuth2Properties properties) { + OAuth2ClientProperties oauth2ClientProperties = new OAuth2ClientProperties(); + properties.getRegistration().setProvider(null); // In case it was set in config + // properties + oauth2ClientProperties.getRegistration() + .put(ConfigClientProperties.OAuth2Properties.CLIENT_REGISTRATION_ID, properties.getRegistration()); + oauth2ClientProperties.getProvider() + .put(ConfigClientProperties.OAuth2Properties.CLIENT_REGISTRATION_ID, properties.getProvider()); + oauth2ClientProperties.afterPropertiesSet(); + + List registrations = new ArrayList<>( + new OAuth2ClientPropertiesMapper(oauth2ClientProperties).asClientRegistrations().values()); + return new InMemoryClientRegistrationRepository(registrations); + } + protected ClientHttpRequestFactory createHttpRequestFactory(ConfigClientProperties client) { if (client.getTls().isEnabled()) { try { From b41bbfd599bbf46e5263ce66e36dfbf148522adc Mon Sep 17 00:00:00 2001 From: prafsoni Date: Tue, 11 Nov 2025 11:29:25 -0800 Subject: [PATCH 2/5] test: Add integration tests for config client oauth2 support Signed-off-by: prafsoni --- pom.xml | 2 + .../pom.xml | 103 ++++++++++++ ...ientRequestTemplateFactoryOAuth2Tests.java | 151 ++++++++++++++++++ .../src/test/resources/test-realm.json | 18 +++ 4 files changed, 274 insertions(+) create mode 100644 spring-cloud-config-client-oauth2-tests/pom.xml create mode 100644 spring-cloud-config-client-oauth2-tests/src/test/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactoryOAuth2Tests.java create mode 100644 spring-cloud-config-client-oauth2-tests/src/test/resources/test-realm.json diff --git a/pom.xml b/pom.xml index 0773957383..51a669f673 100644 --- a/pom.xml +++ b/pom.xml @@ -107,6 +107,7 @@ spring-cloud-config-sample spring-cloud-starter-config spring-cloud-config-client-tls-tests + spring-cloud-config-client-oauth2-tests docs @@ -178,6 +179,7 @@ spring-cloud-config-client-tls-tests + spring-cloud-config-client-oauth2-tests spring-cloud-config-sample diff --git a/spring-cloud-config-client-oauth2-tests/pom.xml b/spring-cloud-config-client-oauth2-tests/pom.xml new file mode 100644 index 0000000000..840ab8398e --- /dev/null +++ b/spring-cloud-config-client-oauth2-tests/pom.xml @@ -0,0 +1,103 @@ + + + 4.0.0 + spring-cloud-config-client-oauth2-tests + jar + Spring Cloud Config Client OAuth2 Tests + + + org.springframework.cloud + spring-cloud-config + 5.0.0-SNAPSHOT + .. + + + https://spring.io + Spring Cloud Config Client OAuth2 Integration Tests + + + + org.springframework.cloud + spring-cloud-config-client + ${project.version} + + + org.springframework.boot + spring-boot + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework + spring-web + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.platform + junit-platform-launcher + test + + + org.springframework.cloud + spring-cloud-test-support + test + + + org.testcontainers + testcontainers-junit-jupiter + test + + + org.springframework.boot + spring-boot-testcontainers + test + + + com.github.dasniko + testcontainers-keycloak + 3.4.0 + test + + + commons-io + commons-io + 2.20.0 + + + + org.mock-server + mockserver-netty + 5.15.0 + test + + + org.mock-server + mockserver-client-java + 5.15.0 + test + + + + + + + + maven-deploy-plugin + + true + + + + + + diff --git a/spring-cloud-config-client-oauth2-tests/src/test/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactoryOAuth2Tests.java b/spring-cloud-config-client-oauth2-tests/src/test/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactoryOAuth2Tests.java new file mode 100644 index 0000000000..760eb8c16d --- /dev/null +++ b/spring-cloud-config-client-oauth2-tests/src/test/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactoryOAuth2Tests.java @@ -0,0 +1,151 @@ +/* + * Copyright 2013-present 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.cloud.config.client; + +import java.net.URI; + +import dasniko.testcontainers.keycloak.KeycloakContainer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.HttpRequest; +import org.mockserver.model.MediaType; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.boot.security.oauth2.client.autoconfigure.OAuth2ClientProperties; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +/** + * IntegrationTest for OAuth2 support in ConfigClientRequestTemplateFactory using Keycloak + * Test container as the Authorization Server and MockServer as a protected resource + * server. + */ +@Tag("DockerRequired") +@Testcontainers +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class ConfigClientRequestTemplateFactoryOAuth2Tests { + + private static final Log log = LogFactory.getLog(ConfigClientRequestTemplateFactoryOAuth2Tests.class); + + @Container + static KeycloakContainer keycloak = new KeycloakContainer().withRealmImportFile("test-realm.json"); // classpath + // resource + + private ClientAndServer mockServer; + + private MockServerClient mockClient; + + @BeforeAll + void startMockServer() { + mockServer = ClientAndServer.startClientAndServer(0); + mockClient = new MockServerClient("localhost", mockServer.getLocalPort()); + } + + @BeforeEach + void resetExpectations() { + mockClient.clear(request().withPath("/secure")); + mockClient.when(request().withMethod("GET").withPath("/secure")).respond(request -> { + if (request.containsHeader("Authorization")) { + String authHeader = request.getFirstHeader("Authorization"); + if (authHeader != null && authHeader.startsWith("Bearer ")) { + return response().withStatusCode(200).withContentType(MediaType.TEXT_PLAIN).withBody("ok"); + } + } + return response().withStatusCode(401); + }); + } + + @AfterAll + void tearDown() { + if (mockClient != null) { + mockClient.close(); + } + if (mockServer != null) { + mockServer.stop(); + } + } + + @Test + void restTemplateAddsBearerTokenFromKeycloakUsingClientCredentials() { + // given OAuth2 client configuration pointing to Keycloak token endpoint + String tokenUri = keycloak.getAuthServerUrl() + "/realms/test-realm/protocol/openid-connect/token"; + + ConfigClientProperties props = new ConfigClientProperties(); + props.getOauth2().setEnabled(true); + + OAuth2ClientProperties.Provider provider = props.getOauth2().getProvider(); + provider.setTokenUri(tokenUri); + + OAuth2ClientProperties.Registration registration = props.getOauth2().getRegistration(); + registration.setClientId("config-client"); + registration.setClientSecret("my-client-secret"); + registration.setAuthorizationGrantType("client_credentials"); + + ConfigClientRequestTemplateFactory factory = new ConfigClientRequestTemplateFactory(log, props); + RestTemplate restTemplate = factory.create(); + + // when + String url = "http://localhost:" + mockServer.getLocalPort() + "/secure"; + ResponseEntity response = restTemplate.getForEntity(URI.create(url), String.class); + + // then + assertThat(response.getStatusCode().is2xxSuccessful()).isTrue(); + assertThat(response.getBody()).isEqualTo("ok"); + + HttpRequest[] recorded = mockClient.retrieveRecordedRequests(request().withPath("/secure")); + assertThat(recorded).hasSize(1); + String authHeader = recorded[0].getFirstHeader("Authorization"); + assertThat(authHeader).isNotNull().startsWith("Bearer "); + } + + @Test + void restTemplateDoesNotAddAuthorizationHeaderWhenOauth2Disabled() { + // given ConfigClientProperties with OAuth2 disabled + ConfigClientProperties props = new ConfigClientProperties(); + props.getOauth2().setEnabled(false); // explicitly disabled + + ConfigClientRequestTemplateFactory factory = new ConfigClientRequestTemplateFactory(log, props); + RestTemplate restTemplate = factory.create(); + + // when + String url = "http://localhost:" + mockServer.getLocalPort() + "/secure"; + + assertThatThrownBy(() -> restTemplate.getForEntity(URI.create(url), String.class)) + .isInstanceOf(org.springframework.web.client.HttpClientErrorException.Unauthorized.class); + + // then + + HttpRequest[] recorded = mockClient.retrieveRecordedRequests(request().withPath("/secure")); + assertThat(recorded).hasSize(1); // only this test's request + assertThat(recorded[0].containsHeader("Authorization")).isFalse(); + } + +} diff --git a/spring-cloud-config-client-oauth2-tests/src/test/resources/test-realm.json b/spring-cloud-config-client-oauth2-tests/src/test/resources/test-realm.json new file mode 100644 index 0000000000..7aaed2819b --- /dev/null +++ b/spring-cloud-config-client-oauth2-tests/src/test/resources/test-realm.json @@ -0,0 +1,18 @@ +{ + "realm": "test-realm", + "enabled": true, + "clients": [ + { + "clientId": "config-client", + "secret": "my-client-secret", + "name": "Config Client", + "protocol": "openid-connect", + "publicClient": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "redirectUris": ["*"], + "webOrigins": ["*"] + } + ] +} + From ff843f55e0cefde3c70778dba868905495aa4c26 Mon Sep 17 00:00:00 2001 From: prafsoni Date: Tue, 11 Nov 2025 11:44:40 -0800 Subject: [PATCH 3/5] test: Add integration tests for config client oauth2 support using issuer uri Signed-off-by: prafsoni --- ...ientRequestTemplateFactoryOAuth2Tests.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/spring-cloud-config-client-oauth2-tests/src/test/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactoryOAuth2Tests.java b/spring-cloud-config-client-oauth2-tests/src/test/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactoryOAuth2Tests.java index 760eb8c16d..221f95f156 100644 --- a/spring-cloud-config-client-oauth2-tests/src/test/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactoryOAuth2Tests.java +++ b/spring-cloud-config-client-oauth2-tests/src/test/java/org/springframework/cloud/config/client/ConfigClientRequestTemplateFactoryOAuth2Tests.java @@ -126,6 +126,39 @@ void restTemplateAddsBearerTokenFromKeycloakUsingClientCredentials() { assertThat(authHeader).isNotNull().startsWith("Bearer "); } + @Test + void restTemplateAddsBearerTokenFromKeycloakUsingClientCredentialsAndIssuerUri() { + // given OAuth2 client configuration pointing to Keycloak issuer endpoint + String issuerUri = keycloak.getAuthServerUrl() + "/realms/test-realm"; + + ConfigClientProperties props = new ConfigClientProperties(); + props.getOauth2().setEnabled(true); + + OAuth2ClientProperties.Provider provider = props.getOauth2().getProvider(); + provider.setIssuerUri(issuerUri); + + OAuth2ClientProperties.Registration registration = props.getOauth2().getRegistration(); + registration.setClientId("config-client"); + registration.setClientSecret("my-client-secret"); + registration.setAuthorizationGrantType("client_credentials"); + + ConfigClientRequestTemplateFactory factory = new ConfigClientRequestTemplateFactory(log, props); + RestTemplate restTemplate = factory.create(); + + // when + String url = "http://localhost:" + mockServer.getLocalPort() + "/secure"; + ResponseEntity response = restTemplate.getForEntity(URI.create(url), String.class); + + // then + assertThat(response.getStatusCode().is2xxSuccessful()).isTrue(); + assertThat(response.getBody()).isEqualTo("ok"); + + HttpRequest[] recorded = mockClient.retrieveRecordedRequests(request().withPath("/secure")); + assertThat(recorded).hasSize(1); + String authHeader = recorded[0].getFirstHeader("Authorization"); + assertThat(authHeader).isNotNull().startsWith("Bearer "); + } + @Test void restTemplateDoesNotAddAuthorizationHeaderWhenOauth2Disabled() { // given ConfigClientProperties with OAuth2 disabled From 52639489ecc96c523ca3c268b41529a3c7d58a39 Mon Sep 17 00:00:00 2001 From: prafsoni Date: Tue, 11 Nov 2025 11:46:35 -0800 Subject: [PATCH 4/5] docs: Update client docs to add an example for oauth2 client config Signed-off-by: prafsoni --- docs/modules/ROOT/pages/client.adoc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/modules/ROOT/pages/client.adoc b/docs/modules/ROOT/pages/client.adoc index 1358d3c6a1..e173c46221 100644 --- a/docs/modules/ROOT/pages/client.adoc +++ b/docs/modules/ROOT/pages/client.adoc @@ -214,6 +214,27 @@ spring: The `spring.cloud.config.password` and `spring.cloud.config.username` values override anything that is provided in the URI. +If you use OAuth2 security on the server, clients need to know the client ID and client secret. +You can specify the client ID and client secret via separate properties, as shown in the following example: + +[source,yaml] +---- + +spring: + cloud: + config: + uri: https://myconfig.mycompany.com + oauth2: + enabled: true + provider: + token-uri: https://auth.acme.com/oauth/token + registration: + client-id: client-id + client-secret: client-secret + authorization-grant-type: client_credentials + +---- + If you deploy your apps on Cloud Foundry, the best way to provide the password is through service credentials (such as in the URI, since it does not need to be in a config file). The following example works locally and for a user-provided service on Cloud Foundry named `configserver`: From b669ef0883258adc2ec40245ac198ccb12be4efd Mon Sep 17 00:00:00 2001 From: prafsoni Date: Thu, 27 Nov 2025 11:07:10 -0800 Subject: [PATCH 5/5] test: fix pom version after rebase Signed-off-by: prafsoni --- spring-cloud-config-client-oauth2-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-config-client-oauth2-tests/pom.xml b/spring-cloud-config-client-oauth2-tests/pom.xml index 840ab8398e..bcf270e921 100644 --- a/spring-cloud-config-client-oauth2-tests/pom.xml +++ b/spring-cloud-config-client-oauth2-tests/pom.xml @@ -10,7 +10,7 @@ org.springframework.cloud spring-cloud-config - 5.0.0-SNAPSHOT + 5.0.1-SNAPSHOT ..