From daa3d457b71896a758995c264977bdd1414ee4d4 Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Thu, 4 Oct 2018 15:15:48 -0700 Subject: [PATCH] Revert OAuth2 Client Registration Grant Type Hierarchy Closes gh-14554 --- .../client/ClientsConfiguredCondition.java | 35 ++-- .../oauth2/client/OAuth2ClientProperties.java | 121 ++++---------- ...entPropertiesEnvironmentPostProcessor.java | 115 ------------- ...h2ClientPropertiesRegistrationAdapter.java | 35 +--- ...itional-spring-configuration-metadata.json | 9 - .../main/resources/META-INF/spring.factories | 4 - ...opertiesEnvironmentPostProcessorTests.java | 158 ------------------ ...entPropertiesRegistrationAdapterTests.java | 131 ++++++--------- .../client/OAuth2ClientPropertiesTests.java | 32 +--- ...iveOAuth2ClientAutoConfigurationTests.java | 2 +- ...istrationRepositoryConfigurationTests.java | 2 +- .../main/asciidoc/spring-boot-features.adoc | 93 +++-------- .../src/main/resources/application.yml | 50 +++--- .../SampleOAuth2ClientApplicationTests.java | 9 +- .../src/main/resources/application.yml | 35 ++-- 15 files changed, 169 insertions(+), 662 deletions(-) delete mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesEnvironmentPostProcessor.java delete mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesEnvironmentPostProcessorTests.java diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/ClientsConfiguredCondition.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/ClientsConfiguredCondition.java index 63ca5eb9a03..203817e6415 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/ClientsConfiguredCondition.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/ClientsConfiguredCondition.java @@ -16,7 +16,6 @@ package org.springframework.boot.autoconfigure.security.oauth2.client; import java.util.Collections; -import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @@ -36,46 +35,32 @@ import org.springframework.core.type.AnnotatedTypeMetadata; * @author Madhura Bhave * @since 2.1.0 */ + public class ClientsConfiguredCondition extends SpringBootCondition { - private static final Bindable> STRING_LOGIN_REGISTRATION_MAP = Bindable - .mapOf(String.class, OAuth2ClientProperties.LoginClientRegistration.class); - - private static final Bindable> STRING_AUTHORIZATION_CODE_REGISTRATION_MAP = Bindable - .mapOf(String.class, - OAuth2ClientProperties.AuthorizationCodeClientRegistration.class); + private static final Bindable> STRING_REGISTRATION_MAP = Bindable + .mapOf(String.class, OAuth2ClientProperties.Registration.class); @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { ConditionMessage.Builder message = ConditionMessage .forCondition("OAuth2 Clients Configured Condition"); - Map registrations = getRegistrations( + Map registrations = getRegistrations( context.getEnvironment()); if (!registrations.isEmpty()) { - return ConditionOutcome.match(message.foundExactly( - "registered clients " + registrations.values().stream().map( - OAuth2ClientProperties.BaseClientRegistration::getClientId) + return ConditionOutcome.match(message + .foundExactly("registered clients " + registrations.values().stream() + .map(OAuth2ClientProperties.Registration::getClientId) .collect(Collectors.joining(", ")))); } return ConditionOutcome.noMatch(message.notAvailable("registered clients")); } - private Map getRegistrations( + private Map getRegistrations( Environment environment) { - Map registrations = new HashMap<>(); - Map loginClientRegistrations = Binder - .get(environment).bind("spring.security.oauth2.client.registration.login", - STRING_LOGIN_REGISTRATION_MAP) - .orElse(Collections.emptyMap()); - Map authCodeClientRegistrations = Binder - .get(environment) - .bind("spring.security.oauth2.client.registration.authorizationcode", - STRING_AUTHORIZATION_CODE_REGISTRATION_MAP) - .orElse(Collections.emptyMap()); - registrations.putAll(loginClientRegistrations); - registrations.putAll(authCodeClientRegistrations); - return registrations; + return Binder.get(environment).bind("spring.security.oauth2.client.registration", + STRING_REGISTRATION_MAP).orElse(Collections.emptyMap()); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientProperties.java index 267d8220039..3d671ee3bcd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientProperties.java @@ -44,116 +44,32 @@ public class OAuth2ClientProperties { /** * OAuth client registrations. */ - private final Registration registration = new Registration(); + private final Map registration = new HashMap<>(); public Map getProvider() { return this.provider; } - public Registration getRegistration() { + public Map getRegistration() { return this.registration; } @PostConstruct public void validate() { - this.getRegistration().getLogin().values().forEach(this::validateRegistration); - this.getRegistration().getAuthorizationCode().values() - .forEach(this::validateRegistration); + this.getRegistration().values().forEach(this::validateRegistration); } - private void validateRegistration(BaseClientRegistration registration) { + private void validateRegistration(Registration registration) { if (!StringUtils.hasText(registration.getClientId())) { throw new IllegalStateException("Client id must not be empty."); } } + /** + * A single client registration. + */ public static class Registration { - /** - * OpenID Connect client registrations. - */ - private Map login = new HashMap<>(); - - /** - * OAuth2 authorization_code client registrations. - */ - private Map authorizationCode = new HashMap<>(); - - public Map getLogin() { - return this.login; - } - - public void setLogin(Map login) { - this.login = login; - } - - public Map getAuthorizationCode() { - return this.authorizationCode; - } - - public void setAuthorizationCode( - Map authorizationCode) { - this.authorizationCode = authorizationCode; - } - - } - - /** - * A single client registration for OpenID Connect login. - */ - public static class LoginClientRegistration extends BaseClientRegistration { - - /** - * Redirect URI. May be left blank when using a pre-defined provider. - */ - private String redirectUri; - - public String getRedirectUri() { - return this.redirectUri; - } - - public void setRedirectUri(String redirectUri) { - this.redirectUri = redirectUri; - } - - @Deprecated - public String getRedirectUriTemplate() { - return getRedirectUri(); - } - - @Deprecated - public void setRedirectUriTemplate(String redirectUri) { - setRedirectUri(redirectUri); - } - - } - - /** - * A single client registration for OAuth2 authorization_code flow. - */ - public static class AuthorizationCodeClientRegistration - extends BaseClientRegistration { - - /** - * Redirect URI for the registration. - */ - private String redirectUri; - - public String getRedirectUri() { - return this.redirectUri; - } - - public void setRedirectUri(String redirectUri) { - this.redirectUri = redirectUri; - } - - } - - /** - * Base class for a single client registration. - */ - public static class BaseClientRegistration { - /** * Reference to the OAuth 2.0 provider to use. May reference an element from the * 'provider' property or used one of the commonly used providers (google, github, @@ -182,6 +98,11 @@ public class OAuth2ClientProperties { */ private String authorizationGrantType; + /** + * Redirect URI. May be left blank when using a pre-defined provider. + */ + private String redirectUri; + /** * Authorization scopes. May be left blank when using a pre-defined provider. */ @@ -232,6 +153,24 @@ public class OAuth2ClientProperties { this.authorizationGrantType = authorizationGrantType; } + public String getRedirectUri() { + return this.redirectUri; + } + + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + @Deprecated + public String getRedirectUriTemplate() { + return getRedirectUri(); + } + + @Deprecated + public void setRedirectUriTemplate(String redirectUri) { + setRedirectUri(redirectUri); + } + public Set getScope() { return this.scope; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesEnvironmentPostProcessor.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesEnvironmentPostProcessor.java deleted file mode 100644 index e25ea4597aa..00000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesEnvironmentPostProcessor.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2012-2018 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 - * - * http://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.boot.autoconfigure.security.oauth2.client; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.Supplier; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.context.config.ConfigFileApplicationListener; -import org.springframework.boot.context.properties.bind.Bindable; -import org.springframework.boot.context.properties.bind.Binder; -import org.springframework.boot.context.properties.source.ConfigurationPropertyName; -import org.springframework.boot.context.properties.source.ConfigurationPropertySource; -import org.springframework.boot.context.properties.source.ConfigurationPropertySources; -import org.springframework.boot.env.EnvironmentPostProcessor; -import org.springframework.core.Ordered; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.MapPropertySource; - -/** - * {@link EnvironmentPostProcessor} that migrates legacy OAuth2 login client properties - * under the `spring.security.oauth2.client.login` prefix. - * - * @author Madhura Bhave - * @since 2.1.0 - */ -public class OAuth2ClientPropertiesEnvironmentPostProcessor - implements EnvironmentPostProcessor, Ordered { - - private static final Bindable> STRING_LEGACY_REGISTRATION_MAP = Bindable - .mapOf(String.class, OAuth2ClientProperties.LoginClientRegistration.class); - - private static final String PREFIX = "spring.security.oauth2.client.registration"; - - private static final String LOGIN_REGISTRATION_PREFIX = PREFIX + ".login."; - - private static final String UPDATED_PROPERTY_SOURCE_SUFFIX = "-updated-oauth-client"; - - private int order = ConfigFileApplicationListener.DEFAULT_ORDER + 1; - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, - SpringApplication application) { - environment.getPropertySources().forEach((propertySource) -> { - String name = propertySource.getName(); - Iterable sources = ConfigurationPropertySources - .from(propertySource); - ConfigurationPropertySource source = sources.iterator().next(); - Binder binder = new Binder(sources); - Map map = new LinkedHashMap<>(); - MapPropertySource updatedPropertySource = new MapPropertySource( - name + UPDATED_PROPERTY_SOURCE_SUFFIX, map); - Map registrations = binder - .bind(PREFIX, STRING_LEGACY_REGISTRATION_MAP) - .orElse(Collections.emptyMap()); - registrations.entrySet() - .forEach((entry) -> addProperties(entry, source, map)); - if (!map.isEmpty()) { - environment.getPropertySources().addBefore(name, updatedPropertySource); - } - }); - } - - private void addProperties( - Map.Entry entry, - ConfigurationPropertySource source, Map map) { - OAuth2ClientProperties.LoginClientRegistration registration = entry.getValue(); - String registrationId = entry.getKey(); - addProperty(registrationId, "client-id", registration::getClientId, map, source); - addProperty(registrationId, "client-secret", registration::getClientSecret, map, - source); - addProperty(registrationId, "client-name", registration::getClientName, map, - source); - addProperty(registrationId, "redirect-uri-template", registration::getRedirectUri, - map, source); - addProperty(registrationId, "authorization-grant-type", - registration::getAuthorizationGrantType, map, source); - addProperty(registrationId, "client-authentication-method", - registration::getClientAuthenticationMethod, map, source); - addProperty(registrationId, "provider", registration::getProvider, map, source); - addProperty(registrationId, "scope", registration::getScope, map, source); - } - - private void addProperty(String registrationId, String property, - Supplier valueSupplier, Map map, - ConfigurationPropertySource source) { - String registrationKey = PREFIX + "." + registrationId + "."; - String loginRegistrationKey = LOGIN_REGISTRATION_PREFIX + registrationId + "."; - if (source.getConfigurationProperty( - ConfigurationPropertyName.of(registrationKey + property)) != null) { - map.put(loginRegistrationKey + property, valueSupplier.get()); - } - } - - @Override - public int getOrder() { - return this.order; - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapter.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapter.java index ee1cd69cbcf..c0bebee9ef9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapter.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapter.java @@ -50,35 +50,20 @@ public final class OAuth2ClientPropertiesRegistrationAdapter { public static Map getClientRegistrations( OAuth2ClientProperties properties) { Map clientRegistrations = new HashMap<>(); - properties.getRegistration().getLogin() - .forEach((key, value) -> clientRegistrations.put(key, - getLoginClientRegistration(key, value, - properties.getProvider()))); - properties.getRegistration().getAuthorizationCode() - .forEach((key, value) -> clientRegistrations.put(key, - getAuthorizationCodeClientRegistration(key, value, - properties.getProvider()))); + properties.getRegistration().forEach((key, value) -> clientRegistrations.put(key, + getClientRegistration(key, value, properties.getProvider()))); return clientRegistrations; } - private static ClientRegistration getAuthorizationCodeClientRegistration( - String registrationId, - OAuth2ClientProperties.AuthorizationCodeClientRegistration properties, - Map providers) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - Builder builder = getBuilder(map, registrationId, properties, providers); - map.from(properties::getRedirectUri).to(builder::redirectUriTemplate); - return builder.build(); - } - - private static Builder getBuilder(PropertyMapper map, String registrationId, - OAuth2ClientProperties.BaseClientRegistration properties, + private static ClientRegistration getClientRegistration(String registrationId, + OAuth2ClientProperties.Registration properties, Map providers) { Builder builder = getBuilderFromIssuerIfPossible(registrationId, properties.getProvider(), providers); if (builder == null) { builder = getBuilder(registrationId, properties.getProvider(), providers); } + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(properties::getClientId).to(builder::clientId); map.from(properties::getClientSecret).to(builder::clientSecret); map.from(properties::getClientAuthenticationMethod) @@ -86,18 +71,10 @@ public final class OAuth2ClientPropertiesRegistrationAdapter { .to(builder::clientAuthenticationMethod); map.from(properties::getAuthorizationGrantType).as(AuthorizationGrantType::new) .to(builder::authorizationGrantType); + map.from(properties::getRedirectUri).to(builder::redirectUriTemplate); map.from(properties::getScope).as((scope) -> StringUtils.toStringArray(scope)) .to(builder::scope); map.from(properties::getClientName).to(builder::clientName); - return builder; - } - - private static ClientRegistration getLoginClientRegistration(String registrationId, - OAuth2ClientProperties.LoginClientRegistration properties, - Map providers) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - Builder builder = getBuilder(map, registrationId, properties, providers); - map.from(properties::getRedirectUri).to(builder::redirectUriTemplate); return builder.build(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 5a4f7509f3c..4b5aaf22d50 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -711,15 +711,6 @@ "name": "spring.session.hazelcast.flush-mode", "defaultValue": "on-save" }, - { - "name" : "spring.security.oauth2.client.registration", - "type" : "java.util.Map", - "description" : "Maps client registration-id to a client registration.", - "deprecation" : { - "replacement" : "spring.security.oauth2.client.registration.login", - "level" : "warning" - } - }, { "name": "spring.session.servlet.filter-dispatcher-types", "defaultValue": [ diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index 6ede25c0412..03dd3e44216 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -7,10 +7,6 @@ org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingL org.springframework.context.ApplicationListener=\ org.springframework.boot.autoconfigure.BackgroundPreinitializer -# Environment Post Processors -org.springframework.boot.env.EnvironmentPostProcessor=\ -org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesEnvironmentPostProcessor - # Auto Configuration Import Listeners org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesEnvironmentPostProcessorTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesEnvironmentPostProcessorTests.java deleted file mode 100644 index 620d35ef382..00000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesEnvironmentPostProcessorTests.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2012-2018 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 - * - * http://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.boot.autoconfigure.security.oauth2.client; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Before; -import org.junit.Test; - -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.StandardEnvironment; -import org.springframework.core.env.SystemEnvironmentPropertySource; -import org.springframework.mock.env.MockEnvironment; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link OAuth2ClientPropertiesEnvironmentPostProcessor}. - * - * @author Madhura Bhave - */ -public class OAuth2ClientPropertiesEnvironmentPostProcessorTests { - - private OAuth2ClientPropertiesEnvironmentPostProcessor postProcessor = new OAuth2ClientPropertiesEnvironmentPostProcessor(); - - private MockEnvironment environment; - - private static final String REGISTRATION_PREFIX = "spring.security.oauth2.client.registration.github-client."; - - private static final String ENVIRONMENT_REGISTRATION_PREFIX = "SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GITHUB-CLIENT_"; - - private static final String LOGIN_REGISTRATION_PREFIX = "spring.security.oauth2.client.registration.login.github-client."; - - @Before - public void setup() { - this.environment = new MockEnvironment(); - } - - @Test - public void postProcessorWhenLegacyPropertiesShouldConvert() { - Map properties = new HashMap<>(); - properties.put(REGISTRATION_PREFIX + "client-id", "my-client-id"); - properties.put(REGISTRATION_PREFIX + "client-secret", "my-client-secret"); - properties.put(REGISTRATION_PREFIX + "redirect-uri-template", - "http://my-redirect-uri.com"); - properties.put(REGISTRATION_PREFIX + "provider", "github"); - properties.put(REGISTRATION_PREFIX + "scope", "user"); - properties.put(REGISTRATION_PREFIX + "client-name", "my-client-name"); - properties.put(REGISTRATION_PREFIX + "authorization-grant-type", - "authorization_code"); - properties.put(REGISTRATION_PREFIX + "client-authentication-method", "FORM"); - MapPropertySource source = new MapPropertySource("test", properties); - this.environment.getPropertySources().addFirst(source); - this.postProcessor.postProcessEnvironment(this.environment, null); - assertPropertyMigration(); - } - - @Test - public void postProcessorDoesNotCopyMissingProperties() { - Map properties = new HashMap<>(); - properties.put(REGISTRATION_PREFIX + "client-id", "my-client-id"); - MapPropertySource source = new MapPropertySource("test", properties); - this.environment.getPropertySources().addFirst(source); - this.postProcessor.postProcessEnvironment(this.environment, null); - assertThat(this.environment.getProperty(LOGIN_REGISTRATION_PREFIX + "client-id")) - .isEqualTo("my-client-id"); - assertThat( - this.environment.getProperty(LOGIN_REGISTRATION_PREFIX + "client-secret")) - .isNull(); - } - - @Test - public void postProcessorWhenLegacyEnvironmentVariablesPropertiesShouldConvert() { - Map properties = new HashMap<>(); - properties.put(ENVIRONMENT_REGISTRATION_PREFIX + "CLIENTID", "my-client-id"); - properties.put(ENVIRONMENT_REGISTRATION_PREFIX + "CLIENTSECRET", - "my-client-secret"); - properties.put(ENVIRONMENT_REGISTRATION_PREFIX + "REDIRECTURITEMPLATE", - "http://my-redirect-uri.com"); - properties.put(ENVIRONMENT_REGISTRATION_PREFIX + "PROVIDER", "github"); - properties.put(ENVIRONMENT_REGISTRATION_PREFIX + "SCOPE", "user"); - properties.put(ENVIRONMENT_REGISTRATION_PREFIX + "CLIENTNAME", "my-client-name"); - properties.put(ENVIRONMENT_REGISTRATION_PREFIX + "AUTHORIZATIONGRANTTYPE", - "authorization_code"); - properties.put(ENVIRONMENT_REGISTRATION_PREFIX + "CLIENTAUTHENTICATIONMETHOD", - "FORM"); - SystemEnvironmentPropertySource source = new SystemEnvironmentPropertySource( - "test-" + StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, - properties); - this.environment.getPropertySources().addFirst(source); - this.postProcessor.postProcessEnvironment(this.environment, null); - assertPropertyMigration(); - } - - @Test - public void postProcessorWhenNewPropertiesShouldDoNothing() { - Map properties = new HashMap<>(); - properties.put(LOGIN_REGISTRATION_PREFIX + "client-id", "my-client-id"); - properties.put(LOGIN_REGISTRATION_PREFIX + "client-secret", "my-client-secret"); - properties.put(LOGIN_REGISTRATION_PREFIX + "redirect-uri-template", - "http://my-redirect-uri.com"); - properties.put(LOGIN_REGISTRATION_PREFIX + "provider", "github"); - properties.put(LOGIN_REGISTRATION_PREFIX + "scope", "user"); - properties.put(LOGIN_REGISTRATION_PREFIX + "client-name", "my-client-name"); - properties.put(LOGIN_REGISTRATION_PREFIX + "authorization-grant-type", - "authorization_code"); - properties.put(LOGIN_REGISTRATION_PREFIX + "client-authentication-method", - "FORM"); - MapPropertySource source = new MapPropertySource("test", properties); - this.environment.getPropertySources().addFirst(source); - MutablePropertySources propertySources = new MutablePropertySources( - this.environment.getPropertySources()); - this.postProcessor.postProcessEnvironment(this.environment, null); - assertPropertyMigration(); - assertThat(this.environment.getPropertySources()) - .containsExactlyElementsOf(propertySources); - } - - private void assertPropertyMigration() { - assertThat(this.environment.getProperty(LOGIN_REGISTRATION_PREFIX + "client-id")) - .isEqualTo("my-client-id"); - assertThat( - this.environment.getProperty(LOGIN_REGISTRATION_PREFIX + "client-secret")) - .isEqualTo("my-client-secret"); - assertThat(this.environment - .getProperty(LOGIN_REGISTRATION_PREFIX + "redirect-uri-template")) - .isEqualTo("http://my-redirect-uri.com"); - assertThat(this.environment.getProperty(LOGIN_REGISTRATION_PREFIX + "provider")) - .isEqualTo("github"); - assertThat(this.environment.getProperty(LOGIN_REGISTRATION_PREFIX + "scope")) - .isEqualTo("user"); - assertThat( - this.environment.getProperty(LOGIN_REGISTRATION_PREFIX + "client-name")) - .isEqualTo("my-client-name"); - assertThat(this.environment - .getProperty(LOGIN_REGISTRATION_PREFIX + "authorization-grant-type")) - .isEqualTo("authorization_code"); - assertThat(this.environment - .getProperty(LOGIN_REGISTRATION_PREFIX + "client-authentication-method")) - .isEqualTo("FORM"); - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapterTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapterTests.java index 1a5bd21e445..d3dfc72cb39 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapterTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesRegistrationAdapterTests.java @@ -26,8 +26,8 @@ import org.junit.After; import org.junit.Test; import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties.LoginClientRegistration; import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties.Provider; +import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties.Registration; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -68,16 +68,16 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { provider.setUserInfoAuthenticationMethod("form"); provider.setUserNameAttribute("sub"); provider.setJwkSetUri("http://example.com/jwk"); - OAuth2ClientProperties.LoginClientRegistration login = new OAuth2ClientProperties.LoginClientRegistration(); - login.setProvider("provider"); - login.setClientId("clientId"); - login.setClientSecret("clientSecret"); - login.setClientAuthenticationMethod("post"); - login.setAuthorizationGrantType("authorization_code"); - login.setRedirectUri("http://example.com/redirect"); - login.setScope(Collections.singleton("scope")); - login.setClientName("clientName"); - properties.getRegistration().getLogin().put("registration", login); + OAuth2ClientProperties.Registration registration = new OAuth2ClientProperties.Registration(); + registration.setProvider("provider"); + registration.setClientId("clientId"); + registration.setClientSecret("clientSecret"); + registration.setClientAuthenticationMethod("post"); + registration.setAuthorizationGrantType("authorization_code"); + registration.setRedirectUri("http://example.com/redirect"); + registration.setScope(Collections.singleton("scope")); + registration.setClientName("clientName"); + properties.getRegistration().put("registration", registration); properties.getProvider().put("provider", provider); Map registrations = OAuth2ClientPropertiesRegistrationAdapter .getClientRegistrations(properties); @@ -110,11 +110,11 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { @Test public void getClientRegistrationsWhenUsingCommonProviderShouldAdapt() { OAuth2ClientProperties properties = new OAuth2ClientProperties(); - OAuth2ClientProperties.LoginClientRegistration login = new OAuth2ClientProperties.LoginClientRegistration(); - login.setProvider("google"); - login.setClientId("clientId"); - login.setClientSecret("clientSecret"); - properties.getRegistration().getLogin().put("registration", login); + OAuth2ClientProperties.Registration registration = new OAuth2ClientProperties.Registration(); + registration.setProvider("google"); + registration.setClientId("clientId"); + registration.setClientSecret("clientSecret"); + properties.getRegistration().put("registration", registration); Map registrations = OAuth2ClientPropertiesRegistrationAdapter .getClientRegistrations(properties); ClientRegistration adapted = registrations.get("registration"); @@ -145,16 +145,16 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { @Test public void getClientRegistrationsWhenUsingCommonProviderWithOverrideShouldAdapt() { OAuth2ClientProperties properties = new OAuth2ClientProperties(); - OAuth2ClientProperties.LoginClientRegistration login = new OAuth2ClientProperties.LoginClientRegistration(); - login.setProvider("google"); - login.setClientId("clientId"); - login.setClientSecret("clientSecret"); - login.setClientAuthenticationMethod("post"); - login.setAuthorizationGrantType("authorization_code"); - login.setRedirectUri("http://example.com/redirect"); - login.setScope(Collections.singleton("scope")); - login.setClientName("clientName"); - properties.getRegistration().getLogin().put("registration", login); + OAuth2ClientProperties.Registration registration = new OAuth2ClientProperties.Registration(); + registration.setProvider("google"); + registration.setClientId("clientId"); + registration.setClientSecret("clientSecret"); + registration.setClientAuthenticationMethod("post"); + registration.setAuthorizationGrantType("authorization_code"); + registration.setRedirectUri("http://example.com/redirect"); + registration.setScope(Collections.singleton("scope")); + registration.setClientName("clientName"); + properties.getRegistration().put("registration", registration); Map registrations = OAuth2ClientPropertiesRegistrationAdapter .getClientRegistrations(properties); ClientRegistration adapted = registrations.get("registration"); @@ -188,9 +188,9 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { @Test public void getClientRegistrationsWhenUnknownProviderShouldThrowException() { OAuth2ClientProperties properties = new OAuth2ClientProperties(); - OAuth2ClientProperties.LoginClientRegistration login = new OAuth2ClientProperties.LoginClientRegistration(); - login.setProvider("missing"); - properties.getRegistration().getLogin().put("registration", login); + OAuth2ClientProperties.Registration registration = new OAuth2ClientProperties.Registration(); + registration.setProvider("missing"); + properties.getRegistration().put("registration", registration); assertThatIllegalStateException() .isThrownBy(() -> OAuth2ClientPropertiesRegistrationAdapter .getClientRegistrations(properties)) @@ -200,10 +200,10 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { @Test public void getClientRegistrationsWhenProviderNotSpecifiedShouldUseRegistrationId() { OAuth2ClientProperties properties = new OAuth2ClientProperties(); - OAuth2ClientProperties.LoginClientRegistration login = new OAuth2ClientProperties.LoginClientRegistration(); - login.setClientId("clientId"); - login.setClientSecret("clientSecret"); - properties.getRegistration().getLogin().put("google", login); + OAuth2ClientProperties.Registration registration = new OAuth2ClientProperties.Registration(); + registration.setClientId("clientId"); + registration.setClientSecret("clientSecret"); + properties.getRegistration().put("google", registration); Map registrations = OAuth2ClientPropertiesRegistrationAdapter .getClientRegistrations(properties); ClientRegistration adapted = registrations.get("google"); @@ -232,47 +232,11 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { assertThat(adapted.getClientName()).isEqualTo("Google"); } - @Test - public void getClientRegistrationsWhenAuthorizationCodeClientShouldAdapt() { - OAuth2ClientProperties properties = new OAuth2ClientProperties(); - OAuth2ClientProperties.AuthorizationCodeClientRegistration registration = new OAuth2ClientProperties.AuthorizationCodeClientRegistration(); - registration.setClientId("clientId"); - registration.setClientSecret("clientSecret"); - registration.setRedirectUri("http://my-redirect-uri.com"); - properties.getRegistration().getAuthorizationCode().put("google", registration); - Map registrations = OAuth2ClientPropertiesRegistrationAdapter - .getClientRegistrations(properties); - ClientRegistration adapted = registrations.get("google"); - ProviderDetails adaptedProvider = adapted.getProviderDetails(); - assertThat(adaptedProvider.getAuthorizationUri()) - .isEqualTo("https://accounts.google.com/o/oauth2/v2/auth"); - assertThat(adaptedProvider.getTokenUri()) - .isEqualTo("https://www.googleapis.com/oauth2/v4/token"); - assertThat(adaptedProvider.getUserInfoEndpoint().getUri()) - .isEqualTo("https://www.googleapis.com/oauth2/v3/userinfo"); - assertThat(adaptedProvider.getUserInfoEndpoint().getAuthenticationMethod()) - .isEqualTo( - org.springframework.security.oauth2.core.AuthenticationMethod.HEADER); - assertThat(adaptedProvider.getJwkSetUri()) - .isEqualTo("https://www.googleapis.com/oauth2/v3/certs"); - assertThat(adapted.getRegistrationId()).isEqualTo("google"); - assertThat(adapted.getClientId()).isEqualTo("clientId"); - assertThat(adapted.getClientSecret()).isEqualTo("clientSecret"); - assertThat(adapted.getRedirectUriTemplate()) - .isEqualTo("http://my-redirect-uri.com"); - assertThat(adapted.getClientAuthenticationMethod()).isEqualTo( - org.springframework.security.oauth2.core.ClientAuthenticationMethod.BASIC); - assertThat(adapted.getAuthorizationGrantType()).isEqualTo( - org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE); - assertThat(adapted.getScopes()).containsExactly("openid", "profile", "email"); - assertThat(adapted.getClientName()).isEqualTo("Google"); - } - @Test public void getClientRegistrationsWhenProviderNotSpecifiedAndUnknownProviderShouldThrowException() { OAuth2ClientProperties properties = new OAuth2ClientProperties(); - OAuth2ClientProperties.LoginClientRegistration login = new OAuth2ClientProperties.LoginClientRegistration(); - properties.getRegistration().getLogin().put("missing", login); + OAuth2ClientProperties.Registration registration = new OAuth2ClientProperties.Registration(); + properties.getRegistration().put("missing", registration); assertThatIllegalStateException() .isThrownBy(() -> OAuth2ClientPropertiesRegistrationAdapter .getClientRegistrations(properties)) @@ -283,7 +247,7 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { @Test public void oidcProviderConfigurationWhenProviderNotSpecifiedOnRegistration() throws Exception { - LoginClientRegistration login = new OAuth2ClientProperties.LoginClientRegistration(); + Registration login = new OAuth2ClientProperties.Registration(); login.setClientId("clientId"); login.setClientSecret("clientSecret"); testOidcConfiguration(login, "okta"); @@ -292,7 +256,7 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { @Test public void oidcProviderConfigurationWhenProviderSpecifiedOnRegistration() throws Exception { - OAuth2ClientProperties.LoginClientRegistration login = new LoginClientRegistration(); + OAuth2ClientProperties.Registration login = new Registration(); login.setProvider("okta-oidc"); login.setClientId("clientId"); login.setClientSecret("clientSecret"); @@ -307,13 +271,13 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { String issuer = this.server.url("").toString(); String cleanIssuerPath = cleanIssuerPath(issuer); setupMockResponse(cleanIssuerPath); - OAuth2ClientProperties.LoginClientRegistration login = new OAuth2ClientProperties.LoginClientRegistration(); - login.setProvider("okta-oidc"); - login.setClientId("clientId"); - login.setClientSecret("clientSecret"); - login.setClientAuthenticationMethod("post"); - login.setRedirectUri("http://example.com/redirect"); - login.setScope(Collections.singleton("user")); + OAuth2ClientProperties.Registration registration = new OAuth2ClientProperties.Registration(); + registration.setProvider("okta-oidc"); + registration.setClientId("clientId"); + registration.setClientSecret("clientSecret"); + registration.setClientAuthenticationMethod("post"); + registration.setRedirectUri("http://example.com/redirect"); + registration.setScope(Collections.singleton("user")); Provider provider = new Provider(); provider.setIssuerUri(issuer); provider.setAuthorizationUri("http://example.com/auth"); @@ -323,7 +287,7 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { provider.setJwkSetUri("http://example.com/jwk"); OAuth2ClientProperties properties = new OAuth2ClientProperties(); properties.getProvider().put("okta-oidc", provider); - properties.getRegistration().getLogin().put("okta", login); + properties.getRegistration().put("okta", registration); Map registrations = OAuth2ClientPropertiesRegistrationAdapter .getClientRegistrations(properties); ClientRegistration adapted = registrations.get("okta"); @@ -347,8 +311,7 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { .isEqualTo("sub"); } - private void testOidcConfiguration( - OAuth2ClientProperties.LoginClientRegistration registration, + private void testOidcConfiguration(OAuth2ClientProperties.Registration registration, String providerId) throws Exception { this.server = new MockWebServer(); this.server.start(); @@ -359,7 +322,7 @@ public class OAuth2ClientPropertiesRegistrationAdapterTests { Provider provider = new Provider(); provider.setIssuerUri(issuer); properties.getProvider().put(providerId, provider); - properties.getRegistration().getLogin().put("okta", registration); + properties.getRegistration().put("okta", registration); Map registrations = OAuth2ClientPropertiesRegistrationAdapter .getClientRegistrations(properties); ClientRegistration adapted = registrations.get("okta"); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesTests.java index bf1016eaec2..a7c010b6a1d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2ClientPropertiesTests.java @@ -18,9 +18,6 @@ package org.springframework.boot.autoconfigure.security.oauth2.client; import org.junit.Test; -import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties.AuthorizationCodeClientRegistration; -import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties.LoginClientRegistration; - import static org.assertj.core.api.Assertions.assertThatIllegalStateException; /** @@ -34,40 +31,21 @@ public class OAuth2ClientPropertiesTests { private OAuth2ClientProperties properties = new OAuth2ClientProperties(); @Test - public void clientIdAbsentForLoginClientsThrowsException() { - LoginClientRegistration registration = new LoginClientRegistration(); + public void clientIdAbsentThrowsException() { + OAuth2ClientProperties.Registration registration = new OAuth2ClientProperties.Registration(); registration.setClientSecret("secret"); registration.setProvider("google"); - this.properties.getRegistration().getLogin().put("foo", registration); + this.properties.getRegistration().put("foo", registration); assertThatIllegalStateException().isThrownBy(this.properties::validate) .withMessageContaining("Client id must not be empty."); } @Test public void clientSecretAbsentShouldNotThrowException() { - LoginClientRegistration registration = new LoginClientRegistration(); + OAuth2ClientProperties.Registration registration = new OAuth2ClientProperties.Registration(); registration.setClientId("foo"); registration.setProvider("google"); - this.properties.getRegistration().getLogin().put("foo", registration); - this.properties.validate(); - } - - @Test - public void clientIdAbsentForAuthorizationCodeClientsThrowsException() { - AuthorizationCodeClientRegistration registration = new AuthorizationCodeClientRegistration(); - registration.setClientSecret("secret"); - registration.setProvider("google"); - this.properties.getRegistration().getAuthorizationCode().put("foo", registration); - assertThatIllegalStateException().isThrownBy(this.properties::validate) - .withMessageContaining("Client id must not be empty."); - } - - @Test - public void clientSecretAbsentForAuthorizationCodeClientDoesNotThrowException() { - AuthorizationCodeClientRegistration registration = new AuthorizationCodeClientRegistration(); - registration.setClientId("foo"); - registration.setProvider("google"); - this.properties.getRegistration().getAuthorizationCode().put("foo", registration); + this.properties.getRegistration().put("foo", registration); this.properties.validate(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/reactive/ReactiveOAuth2ClientAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/reactive/ReactiveOAuth2ClientAutoConfigurationTests.java index a9a140a9294..f280682ea37 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/reactive/ReactiveOAuth2ClientAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/reactive/ReactiveOAuth2ClientAutoConfigurationTests.java @@ -52,7 +52,7 @@ public class ReactiveOAuth2ClientAutoConfigurationTests { .withConfiguration( AutoConfigurations.of(ReactiveOAuth2ClientAutoConfiguration.class)); - private static final String REGISTRATION_PREFIX = "spring.security.oauth2.client.registration.login"; + private static final String REGISTRATION_PREFIX = "spring.security.oauth2.client.registration"; @Test public void autoConfigurationShouldBackOffForServletEnvironments() { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfigurationTests.java index 74dfe19e144..dcea65025c5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfigurationTests.java @@ -33,7 +33,7 @@ public class OAuth2ClientRegistrationRepositoryConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); - private static final String REGISTRATION_PREFIX = "spring.security.oauth2.client.registration.login"; + private static final String REGISTRATION_PREFIX = "spring.security.oauth2.client.registration"; @Test public void clientRegistrationRepositoryBeanShouldNotBeCreatedWhenPropertiesAbsent() { diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 45a468de1d5..fbd2216c01c 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -3264,13 +3264,31 @@ Spring. ==== Client If you have `spring-security-oauth2-client` on your classpath, you can take advantage of some auto-configuration to make it easy to set up an OAuth2/Open ID Connect clients. This configuration -makes use of the properties under `OAuth2ClientProperties`. +makes use of the properties under `OAuth2ClientProperties`. The same properties are applicable to both servlet and reactive applications. -You can register multiple OAuth2/OpenID Connect providers under the `spring.security.oauth2.client.provider` -prefix, as shown in the following example: +You can register multiple OAuth2 clients and providers under the +`spring.security.oauth2.client` prefix, as shown in the following example: [source,properties,indent=0] ---- + spring.security.oauth2.client.registration.my-client-1.client-id=abcd + spring.security.oauth2.client.registration.my-client-1.client-secret=password + spring.security.oauth2.client.registration.my-client-1.client-name=Client for user scope + spring.security.oauth2.client.registration.my-client-1.provider=my-oauth-provider + spring.security.oauth2.client.registration.my-client-1.scope=user + spring.security.oauth2.client.registration.my-client-1.redirect-uri-template=http://my-redirect-uri.com + spring.security.oauth2.client.registration.my-client-1.client-authentication-method=basic + spring.security.oauth2.client.registration.my-client-1.authorization-grant-type=authorization_code + + spring.security.oauth2.client.registration.my-client-2.client-id=abcd + spring.security.oauth2.client.registration.my-client-2.client-secret=password + spring.security.oauth2.client.registration.my-client-2.client-name=Client for email scope + spring.security.oauth2.client.registration.my-client-2.provider=my-oauth-provider + spring.security.oauth2.client.registration.my-client-2.scope=email + spring.security.oauth2.client.registration.my-client-2.redirect-uri-template=http://my-redirect-uri.com + spring.security.oauth2.client.registration.my-client-2.client-authentication-method=basic + spring.security.oauth2.client.registration.my-client-2.authorization-grant-type=authorization_code + spring.security.oauth2.client.provider.my-oauth-provider.authorization-uri=http://my-auth-server/oauth/authorize spring.security.oauth2.client.provider.my-oauth-provider.token-uri=http://my-auth-server/oauth/token spring.security.oauth2.client.provider.my-oauth-provider.user-info-uri=http://my-auth-server/userinfo @@ -3294,33 +3312,6 @@ Provider can be configured with the `issuer-uri`: -[[boot-features-security-oauth2-login-client-registration]] -===== OpenID Connect Login client registration - -You can register multiple Open ID Connect clients under the -`spring.security.oauth2.client.registration.login` prefix, as shown in the following example: - -[source,properties,indent=0] ----- - spring.security.oauth2.client.registration.login.my-client-1.client-id=abcd - spring.security.oauth2.client.registration.login.my-client-1.client-secret=password - spring.security.oauth2.client.registration.login.my-client-1.client-name=Client for user scope - spring.security.oauth2.client.registration.login.my-client-1.provider=my-oauth-provider - spring.security.oauth2.client.registration.login.my-client-1.scope=user - spring.security.oauth2.client.registration.login.my-client-1.redirect-uri=http://localhost:8080/login/oauth2/code/my-client-1 - spring.security.oauth2.client.registration.login.my-client-1.client-authentication-method=basic - spring.security.oauth2.client.registration.login.my-client-1.authorization-grant-type=authorization_code - - spring.security.oauth2.client.registration.login.my-client-2.client-id=abcd - spring.security.oauth2.client.registration.login.my-client-2.client-secret=password - spring.security.oauth2.client.registration.login.my-client-2.client-name=Client for email scope - spring.security.oauth2.client.registration.login.my-client-2.provider=my-oauth-provider - spring.security.oauth2.client.registration.login.my-client-2.scope=email - spring.security.oauth2.client.registration.login.my-client-2.redirect-uri=http://localhost:8080/login/oauth2/code/my-client-2 - spring.security.oauth2.client.registration.login.my-client-2.client-authentication-method=basic - spring.security.oauth2.client.registration.login.my-client-2.authorization-grant-type=authorization_code ----- - By default, Spring Security's `OAuth2LoginAuthenticationFilter` only processes URLs matching `/login/oauth2/code/*`. If you want to customize the `redirect-uri` to use a different pattern, you need to provide configuration to process that custom pattern. @@ -3344,36 +3335,6 @@ public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter { } ---- -The same properties are applicable to both servlet and reactive applications. - - -[[boot-features-security-oauth2-authorization-code-client-registration]] -===== OAuth2 Authorization Code client registration - -You can register multiple OAuth2 `authorization_code` clients under the -`spring.security.oauth2.client.registration.authorization-code` prefix, as shown in the following example: - -[source,properties,indent=0] ----- - spring.security.oauth2.client.registration.authorization-code.my-client-1.client-id=abcd - spring.security.oauth2.client.registration.authorization-code.my-client-1.client-secret=password - spring.security.oauth2.client.registration.authorization-code.my-client-1.client-name=Client for user scope - spring.security.oauth2.client.registration.authorization-code.my-client-1.provider=my-oauth-provider - spring.security.oauth2.client.registration.authorization-code.my-client-1.scope=user - spring.security.oauth2.client.registration.authorization-code.my-client-1.redirect-uri=http://my-redirect-uri.com - spring.security.oauth2.client.registration.authorization-code.my-client-1.client-authentication-method=basic - spring.security.oauth2.client.registration.authorization-code.my-client-1.authorization-grant-type=authorization_code - - spring.security.oauth2.client.registration.authorization-code.my-client-2.client-id=abcd - spring.security.oauth2.client.registration.authorization-code.my-client-2.client-secret=password - spring.security.oauth2.client.registration.authorization-code.my-client-2.client-name=Client for email scope - spring.security.oauth2.client.registration.authorization-code.my-client-2.provider=my-oauth-provider - spring.security.oauth2.client.registration.authorization-code.my-client-2.scope=email - spring.security.oauth2.client.registration.authorization-code.my-client-2.redirect-uri=http://my-redirect-uri.com - spring.security.oauth2.client.registration.authorization-code.my-client-2.client-authentication-method=basic - spring.security.oauth2.client.registration.authorization-code.my-client-2.authorization-grant-type=authorization_code ----- - [[boot-features-security-oauth2-common-providers]] @@ -3383,19 +3344,19 @@ we provide a set of provider defaults (`google`, `github`, `facebook`, and `okta respectively). If you do not need to customize these providers, you can set the `provider` attribute to -the one for which you need to infer defaults. Also, if the ID of your client matches the +the one for which you need to infer defaults. Also, if the key for the client registration matches a default supported provider, Spring Boot infers that as well. In other words, the two configurations in the following example use the Google provider: [source,properties,indent=0] ---- - spring.security.oauth2.client.registration.login.my-client.client-id=abcd - spring.security.oauth2.client.registration.login.my-client.client-secret=password - spring.security.oauth2.client.registration.login.my-client.provider=google + spring.security.oauth2.client.registration.my-client.client-id=abcd + spring.security.oauth2.client.registration.my-client.client-secret=password + spring.security.oauth2.client.registration.my-client.provider=google - spring.security.oauth2.client.registration.login.google.client-id=abcd - spring.security.oauth2.client.registration.login.google.client-secret=password + spring.security.oauth2.client.registration.google.client-id=abcd + spring.security.oauth2.client.registration.google.client-secret=password ---- diff --git a/spring-boot-samples/spring-boot-sample-oauth2-client/src/main/resources/application.yml b/spring-boot-samples/spring-boot-sample-oauth2-client/src/main/resources/application.yml index cef19f07115..dab564dd4de 100644 --- a/spring-boot-samples/spring-boot-sample-oauth2-client/src/main/resources/application.yml +++ b/spring-boot-samples/spring-boot-sample-oauth2-client/src/main/resources/application.yml @@ -3,32 +3,30 @@ spring: oauth2: client: registration: - login: - github-client-1: - client-id: ${APP-CLIENT-ID} - client-secret: ${APP-CLIENT-SECRET} - client-name: Github user - provider: github - scope: user - redirect-uri: http://localhost:8080/login/oauth2/code/github - github-client-2: - client-id: ${APP-CLIENT-ID} - client-secret: ${APP-CLIENT-SECRET} - client-name: Github email - provider: github - scope: user:email - redirect-uri: http://localhost:8080/login/oauth2/code/github - yahoo-oidc: - client-id: ${YAHOO-CLIENT-ID} - client-secret: ${YAHOO-CLIENT-SECRET} - authorization_code: - github-repos: - client-id: ${APP-CLIENT-ID} - client-secret: ${APP-CLIENT-SECRET} - scope: public_repo - redirect-uri: "{baseUrl}/github-repos" - provider: github - client-name: GitHub Repositories + github-client-1: + client-id: ${APP-CLIENT-ID} + client-secret: ${APP-CLIENT-SECRET} + client-name: Github user + provider: github + scope: user + redirect-uri: http://localhost:8080/login/oauth2/code/github + github-client-2: + client-id: ${APP-CLIENT-ID} + client-secret: ${APP-CLIENT-SECRET} + client-name: Github email + provider: github + scope: user:email + redirect-uri: http://localhost:8080/login/oauth2/code/github + yahoo-oidc: + client-id: ${YAHOO-CLIENT-ID} + client-secret: ${YAHOO-CLIENT-SECRET} + github-repos: + client-id: ${APP-CLIENT-ID} + client-secret: ${APP-CLIENT-SECRET} + scope: public_repo + redirect-uri: "{baseUrl}/github-repos" + provider: github + client-name: GitHub Repositories provider: yahoo-oidc: issuer-uri: https://api.login.yahoo.com/ \ No newline at end of file diff --git a/spring-boot-samples/spring-boot-sample-oauth2-client/src/test/java/sample/oauth2/client/SampleOAuth2ClientApplicationTests.java b/spring-boot-samples/spring-boot-sample-oauth2-client/src/test/java/sample/oauth2/client/SampleOAuth2ClientApplicationTests.java index 590a19dfbb8..203b2a5bb94 100644 --- a/spring-boot-samples/spring-boot-sample-oauth2-client/src/test/java/sample/oauth2/client/SampleOAuth2ClientApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-oauth2-client/src/test/java/sample/oauth2/client/SampleOAuth2ClientApplicationTests.java @@ -53,20 +53,13 @@ public class SampleOAuth2ClientApplicationTests { } @Test - public void loginShouldHaveBothOAuth2LoginClientsToChooseFrom() { + public void loginShouldHaveAllOAuth2ClientsToChooseFrom() { ResponseEntity entity = this.restTemplate.getForEntity("/login", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("/oauth2/authorization/yahoo"); assertThat(entity.getBody()).contains("/oauth2/authorization/github-client-1"); assertThat(entity.getBody()).contains("/oauth2/authorization/github-client-2"); - } - - @Test - public void authorizationCodeClientIsPresent() { - ResponseEntity entity = this.restTemplate.getForEntity("/login", - String.class); - assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("/oauth2/authorization/github-repos"); } diff --git a/spring-boot-samples/spring-boot-sample-reactive-oauth2-client/src/main/resources/application.yml b/spring-boot-samples/spring-boot-sample-reactive-oauth2-client/src/main/resources/application.yml index 77e1608d3eb..63fdcfd5b87 100644 --- a/spring-boot-samples/spring-boot-sample-reactive-oauth2-client/src/main/resources/application.yml +++ b/spring-boot-samples/spring-boot-sample-reactive-oauth2-client/src/main/resources/application.yml @@ -3,24 +3,23 @@ spring: oauth2: client: registration: - login: - github-client-1: - client-id: ${APP-CLIENT-ID} - client-secret: ${APP-CLIENT-SECRET} - client-name: Github user - provider: github - scope: user - redirect-uri: http://localhost:8080/login/oauth2/code/github - github-client-2: - client-id: ${APP-CLIENT-ID} - client-secret: ${APP-CLIENT-SECRET} - client-name: Github email - provider: github - scope: user:email - redirect-uri: http://localhost:8080/login/oauth2/code/github - yahoo-oidc: - client-id: ${YAHOO-CLIENT-ID} - client-secret: ${YAHOO-CLIENT-SECRET} + github-client-1: + client-id: ${APP-CLIENT-ID} + client-secret: ${APP-CLIENT-SECRET} + client-name: Github user + provider: github + scope: user + redirect-uri: http://localhost:8080/login/oauth2/code/github + github-client-2: + client-id: ${APP-CLIENT-ID} + client-secret: ${APP-CLIENT-SECRET} + client-name: Github email + provider: github + scope: user:email + redirect-uri: http://localhost:8080/login/oauth2/code/github + yahoo-oidc: + client-id: ${YAHOO-CLIENT-ID} + client-secret: ${YAHOO-CLIENT-SECRET} provider: yahoo-oidc: issuer-uri: https://api.login.yahoo.com/ \ No newline at end of file