Revert OAuth2 Client Registration Grant Type Hierarchy

Closes gh-14554
This commit is contained in:
Madhura Bhave 2018-10-04 15:15:48 -07:00
parent 546bd89f2e
commit daa3d457b7
15 changed files with 169 additions and 662 deletions

View File

@ -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<Map<String, OAuth2ClientProperties.LoginClientRegistration>> STRING_LOGIN_REGISTRATION_MAP = Bindable
.mapOf(String.class, OAuth2ClientProperties.LoginClientRegistration.class);
private static final Bindable<Map<String, OAuth2ClientProperties.AuthorizationCodeClientRegistration>> STRING_AUTHORIZATION_CODE_REGISTRATION_MAP = Bindable
.mapOf(String.class,
OAuth2ClientProperties.AuthorizationCodeClientRegistration.class);
private static final Bindable<Map<String, OAuth2ClientProperties.Registration>> 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<String, OAuth2ClientProperties.BaseClientRegistration> registrations = getRegistrations(
Map<String, OAuth2ClientProperties.Registration> 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<String, OAuth2ClientProperties.BaseClientRegistration> getRegistrations(
private Map<String, OAuth2ClientProperties.Registration> getRegistrations(
Environment environment) {
Map<String, OAuth2ClientProperties.BaseClientRegistration> registrations = new HashMap<>();
Map<String, OAuth2ClientProperties.LoginClientRegistration> loginClientRegistrations = Binder
.get(environment).bind("spring.security.oauth2.client.registration.login",
STRING_LOGIN_REGISTRATION_MAP)
.orElse(Collections.emptyMap());
Map<String, OAuth2ClientProperties.AuthorizationCodeClientRegistration> 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());
}
}

View File

@ -44,116 +44,32 @@ public class OAuth2ClientProperties {
/**
* OAuth client registrations.
*/
private final Registration registration = new Registration();
private final Map<String, Registration> registration = new HashMap<>();
public Map<String, Provider> getProvider() {
return this.provider;
}
public Registration getRegistration() {
public Map<String, Registration> 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<String, LoginClientRegistration> login = new HashMap<>();
/**
* OAuth2 authorization_code client registrations.
*/
private Map<String, AuthorizationCodeClientRegistration> authorizationCode = new HashMap<>();
public Map<String, LoginClientRegistration> getLogin() {
return this.login;
}
public void setLogin(Map<String, LoginClientRegistration> login) {
this.login = login;
}
public Map<String, AuthorizationCodeClientRegistration> getAuthorizationCode() {
return this.authorizationCode;
}
public void setAuthorizationCode(
Map<String, AuthorizationCodeClientRegistration> 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<String> getScope() {
return this.scope;
}

View File

@ -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<Map<String, OAuth2ClientProperties.LoginClientRegistration>> 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<ConfigurationPropertySource> sources = ConfigurationPropertySources
.from(propertySource);
ConfigurationPropertySource source = sources.iterator().next();
Binder binder = new Binder(sources);
Map<String, Object> map = new LinkedHashMap<>();
MapPropertySource updatedPropertySource = new MapPropertySource(
name + UPDATED_PROPERTY_SOURCE_SUFFIX, map);
Map<String, OAuth2ClientProperties.LoginClientRegistration> 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<String, OAuth2ClientProperties.LoginClientRegistration> entry,
ConfigurationPropertySource source, Map<String, Object> 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<Object> valueSupplier, Map<String, Object> 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;
}
}

View File

@ -50,35 +50,20 @@ public final class OAuth2ClientPropertiesRegistrationAdapter {
public static Map<String, ClientRegistration> getClientRegistrations(
OAuth2ClientProperties properties) {
Map<String, ClientRegistration> 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<String, Provider> 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<String, Provider> 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<String, Provider> providers) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
Builder builder = getBuilder(map, registrationId, properties, providers);
map.from(properties::getRedirectUri).to(builder::redirectUriTemplate);
return builder.build();
}

View File

@ -711,15 +711,6 @@
"name": "spring.session.hazelcast.flush-mode",
"defaultValue": "on-save"
},
{
"name" : "spring.security.oauth2.client.registration",
"type" : "java.util.Map<java.lang.String,org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties.LoginClientRegistration>",
"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": [

View File

@ -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

View File

@ -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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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");
}
}

View File

@ -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<String, ClientRegistration> 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<String, ClientRegistration> 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<String, ClientRegistration> 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<String, ClientRegistration> 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<String, ClientRegistration> 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<String, ClientRegistration> 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<String, ClientRegistration> registrations = OAuth2ClientPropertiesRegistrationAdapter
.getClientRegistrations(properties);
ClientRegistration adapted = registrations.get("okta");

View File

@ -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();
}

View File

@ -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() {

View File

@ -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() {

View File

@ -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
----

View File

@ -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/

View File

@ -53,20 +53,13 @@ public class SampleOAuth2ClientApplicationTests {
}
@Test
public void loginShouldHaveBothOAuth2LoginClientsToChooseFrom() {
public void loginShouldHaveAllOAuth2ClientsToChooseFrom() {
ResponseEntity<String> 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<String> entity = this.restTemplate.getForEntity("/login",
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).contains("/oauth2/authorization/github-repos");
}

View File

@ -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/