Skip to content

Add auto-configuration for spring-security-oauth2-client #10235

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

jgrandja
Copy link

@jgrandja jgrandja commented Sep 9, 2017

This PR provides auto-configuration for Spring Security 5.0 OAuth 2.0 / OpenID Connect 1.0 client support.

The default auto-configuration will register a ClientRegistrationRepository with the context and
will enable httpSecurity.oauth2Login() based on a number of conditions.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 9, 2017
@jgrandja
Copy link
Author

jgrandja commented Sep 9, 2017

Related #10236

Copy link
Member

@wilkinsona wilkinsona left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, @jgrandja.

Do you have an opinion on what should happen to the existing OAuth-related auto-configuration in Boot? Given that the separate OAuth project is, as I undestand it, kinda dormant now, it would seem desirable for it to be dropped in Boot 2.0 so that we're not tied into maintaining it for longer than we'd like even if that means losing some auto-configured functionality.

* @author Joe Grandja
* @since 2.0.0
*/
public class ClientPropertyDefaultsEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be replaced with one or more @ConfigurationProperties classes with fields initialised with the desired default values.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did look at potentially using @ConfigurationProperties initially but it did not suit my requirements because it supports a static base property path whereas the base property path for client properties is dynamic.

Given the following format for client properties:

[client-property-prefix].[client-key].[property-name]=[property-value]

for example, security.oauth2.client.google.client-id=google-client-id

the [client-key] (google) is dynamic and may be any value assigned by the user.

Here's a use case. The user wants to configure the following 2 google clients.

security.oauth2.client.google-login.client-id=google-login-client-id
and
security.oauth2.client.google-calendar.client-id=google-calendar-client-id

The google-login client will be used for oauth2Login() whereas the google-calendar client will be used for accessing the Calendar API.

The user is not fixed to using google for the client-key. They may choose whatever name for client-key that makes sense for their configuration.

NOTE: The client-key is only used as a logical separator for client configurations. Nothing more than that. It is not used when auto-configuring ClientRegistration instances. Another thing to note as I indirectly mentioned is that the user is able to configure more than one client as they wish - each configuration separated by the client-key. This is a new capability in Spring Security 5 compared to spring-security-oauth where you are limited to configuring only 1 client.

We're also providing a set of common defaults for well-known providers via spring-security-oauth2-client-defaults.properties in order to minimize the configuration for the user. So if the user wants to configure 1 google client only than they can leverage the defaults and would only have to configure the following:

security.oauth2.client.google.client-id
security.oauth2.client.google.client-secret

However, if they decided to name their client-key to google-login instead, than they can still leverage the default property values in the Environment but their configuration would need to look like this:

security.oauth2.client.google-login.client-id=google-client-id
security.oauth2.client.google-login.client-secret=google-client-secret
security.oauth2.client.google-login.authorization-uri=${security.oauth2.client.google.authorization-uri}
security.oauth2.client.google-login.token-uri=${security.oauth2.client.google.token-uri}
...

...leveraging property placeholders.

Hopefully that explains things. And if you have another suggestion for implementation than please let me know.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation.

You could largely do this with @ConfigurationProperties with a Map<String, Foo> property where Foo would be a pojo with client-id, client-secret etc properties on it. This is preferable to using the environment directly as it's strongly typed and will provide some auto-completion and documentation in a developer's IDE. I say some, as you won't get any metadata (and therefore IDE support) for anything nested in the map. That situation will improve when we implement #9945 but it's out of scope for 2.0.

/cc @snicoll

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wilkinsona I'm not sure I follow you? Let's go by example. Given that @ConfigurationProperties is allowed on Type and Method only, these are my 2 options:

Option 1

	@ConfigurationProperties(value = "security.oauth2.client.google")
	public ClientRegistrationProperties googleClientConfig() {
		return new ClientRegistrationProperties();
	}

Option 2

@ConfigurationProperties(value = "security.oauth2.client.google")
public class GoogleClientConfig extends ClientRegistrationProperties {
}

Option 2 is redundant as I'm simply extending the existing ClientRegistrationProperties class and provide no extra value here. So this option is not really an option.

Option 1 is an extra configuration step that can be avoided. So for each client I configure in my application.yml or defaults.yml I need to also use @ConfigurationProperties. Why? It's really an extra step that IMO is not needed.

Not to mention, as part of the introspection of client properties in the Environment, I'm checking for the required client-id property and if it's not provided than I don't configure the client. How can I do this validation by-pass with @ConfigurationProperties?

Moreover, we do not want to expose ClientRegistration instance as beans in the context. The only bean that should be in the context is a ClientRegistrationRepository bean that is composed of one or more ClientRegistration's

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not your only two options for what you need to bind. Here is a simple example:

@ConfigurationProperties(value = "security.oauth2")
public class OAuth2Properties {

    private final Map<String,ClientRegistrationProperties> client = new HashMap<>();

    public Map<String,ClientRegistrationProperties> getClient() { return this.client; }

}

With this setup, you can bind any client via the map, something like security.oauth2.client.google.xyz where xyz is a property of ClientRegistrationProperties.

Having said that, I'd be in favour of restructing that a bit, something like security.oauth2.client.providers or something. The code above is a bit weird, this is much better IMO:

@ConfigurationProperties(value = "security.oauth2.client")
public class OAuth2ClientProperties {

    private final Map<String,ClientRegistrationProperties> providers = new HashMap<>();

    public Map<String,ClientRegistrationProperties> getProviders() { return this.providers; }

}

Copy link
Author

@jgrandja jgrandja Sep 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@snicoll @wilkinsona I tried your suggestion for binding the clients as follows:

@ConfigurationProperties(prefix = "security.oauth2.client")
public class OAuth2ClientsProperties {

	private Map<String, ClientRegistrationProperties> clients = new HashMap<>();

	public Map<String, ClientRegistrationProperties> getClients() {
		return clients;
	}

	public void setClients(Map<String, ClientRegistrationProperties> clients) {
		this.clients = clients;
	}
}

But this did not work since the base property path used for binding would be security.oauth2.client.clients based on this structure but the clients are configured in the Environment on this base path security.oauth2.client.<client-key>, for example, security.oauth2.client.google, security.oauth2.client.github, etc.

To get it to work, the structure is this:

@ConfigurationProperties(prefix = OAuth2ClientsProperties.CLIENT_PROPERTY_PREFIX)
public class OAuth2ClientsProperties extends HashMap<String, ClientRegistrationProperties> {

	public static final String CLIENT_PROPERTY_PREFIX = "security.oauth2.client";

}

I will admit that I don't like the fact that I have to extend HashMap even though the client properties is a Map. As you are reviewing things, maybe you can suggest an alternative option?

Copy link
Member

@snicoll snicoll Sep 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jgrandja I gave you a code sample for that, see OAuth2Properties (there is no need for a setter if the map is initialized).

As far as I know we decide what the path will be. If we decide that the path is security.oauth2.client.providers so bet it. In that case the second example I gave would work.

Sorry, but I don't understand what the problem is. I think we'd like this to move to spring.security.oauth2.* anyway.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@snicoll Sorry for the confusion but honestly I'm confused as well. In your initial comment, you did suggest OAuth2Properties but shortly after that you said...

Having said that, I'd be in favour of restructing that a bit, something like security.oauth2.client.providers or something. The code above is a bit weird...

In your last comment, you said

I think we'd like this to move to spring.security.oauth2.* anyway.

Can you please confirm if you want spring at the start of the prefix? This is new and threw me for a loop.

Again, I apologize for the confusion but I want to make sure I get things right so we're not going back and forth here. I don't want to waste your time or mine.

I just pushed an update that includes this:

@ConfigurationProperties(prefix = "security.oauth2")
public class OAuth2Properties {

	private Map<String, ClientRegistrationProperties> clients = new LinkedHashMap<>();

	public Map<String, ClientRegistrationProperties> getClients() {
		return this.clients;
	}

	public void setClients(Map<String, ClientRegistrationProperties> clients) {
		this.clients = clients;
	}
}

If this is not what you expect than please let me where to correct and I'll get it done quick.
Thanks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the back and forth is because the only thing I am doing here is answering you on the technicality. I gave you options that work and answers the technical concern that you've raised.

Can you please confirm if you want spring at the start of the prefix? This is new and threw me for a loop.

I don't know and it doesn't matter. If/Once the PR is in a good shape to be merged, we can rename the prefix ourselves. It's really not a big deal.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@snicoll I'm really hoping we can get this into M4 this Thursday. Please let me know what I need to do on my end to make this happen. Thanks.

return getClientPropertiesByClient(environment).keySet();
}

static Map<String, Map> getClientPropertiesByClient(Environment environment) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unusual for an auto-configuration class to use the Environment directly. Ideally, this should be replaced with @ConfigurationProperties classes that I proposed above.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment

.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

@Order(1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this ordered? It looks like it's to ensure that it is processed before OAuth2LoginConfiguration. I am not sure that it will be guaranteed to have that effect when they're inner-classes rather than classes registered directly with the context. Our preferred approach for this is to use @Import where the order of the referenced classes is guaranteed to be honoured.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've split-up OAuth2LoginConfiguration into ClientRegistrationRepositoryAutoConfiguration and OAuth2LoginAutoConfiguration and leveraged @AutoConfigureBefore to ensure the correct ordering. Will push those changes shortly.

@Order(2)
@ConditionalOnMissingBean(WebSecurityConfiguration.class)
@ConditionalOnBean(ClientRegistrationRepository.class)
@EnableWebSecurity
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be annotated with @EnableWebSecurity. IIRC, we've never needed it in multiple places in other Spring Boot security configuration classes. I think we just need to make sure that the auto-configuration class that enables web security is doing its job at the right time relative to these configuration classes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Will replace @EnableWebSecurity with @Configuration

// @formatter:on

private void registerUserNameAttributeNames(OAuth2LoginConfigurer<HttpSecurity> oauth2LoginConfigurer) throws Exception {
getClientPropertiesByClient(this.environment).entrySet().stream().forEach(e -> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.forEach() rather than .stream().forEach() would work here wouldn't it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it would. Will update.

}

@Test
public void refreshContextWhenNoOverridesThenLoadDefaultConfiguration()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it makes sense to do so, it'd be nice to split this test up a bit

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests will be much smaller now given that I split up the auto-config's into 2 classes.

*
* @author Joe Grandja
*/
public class OAuth2ClientAutoConfigurationTests {
Copy link
Member

@wilkinsona wilkinsona Sep 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests would benefit from using our new WebApplicationContextRunner. We could take care of that as part of merging things. It may solve the @EnableWebSecurity-related problem as, among other things, it takes care of ordering auto-configuration classes correctly.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the tests to ensure AnnotationConfigWebApplicationContext.register() is called in the correct order for the auto-config classes. All tests are passing now. Let me see if I can integrate WebApplicationContextRunner instead.

Copy link
Author

@jgrandja jgrandja Sep 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried integrating WebApplicationContextRunner, however, I couldn't get it working because ClientPropertyDefaultsEnvironmentPostProcessor did not postProcess and it needs to.

Looking at the API, it wasn't clear on how to register ClientPropertyDefaultsEnvironmentPostProcessor with the runner.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like another reason not to use the environment post processor approach to me. Another is that you can't switch it off, i.e. you'll always get the property source in the environment, whether or not you're using Spring Security.

I don't think we'll be comfortable merging this until the use of an EPP has been replaced with something else.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property source will only be added if there are client properties available in the Environment if configured by the user. Otherwise, it won't be added.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the correction. I'd missed that. Unfortunately, it doesn't change my opinion about using an EnvironmentPostProcessor here. It would be the only auto-configuration in Boot that uses one. We're consistent in using @ConfigurationProperties for this pretty much everywhere else in Boot and I'd like that to continue. Can you please explore the Map<String, Foo> approach that I described earlier?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment

@jgrandja
Copy link
Author

jgrandja commented Sep 11, 2017

@wilkinsona I pushed a couple commits based on your feedback.

@jgrandja
Copy link
Author

@wilkinsona Good question ...regarding dropping the current OAuth-related auto-configuration in Boot 2.0.

FYI, our plan is to bring Resource Server functionality into 5.1 which I'm thinking will be released around March 2018. At this point we'll have full client and resource server support. We will tackle the Authorization Server next after that but this will be a much larger undertaking that may even take up to 1 year.

I would ask this question... Would it be sufficient to have auto-configuration for client and resource server functionality only and not authorization server? I personally would answer yes.

Auto-configuration for Authorization Server IMO is risky and probably should be avoided.

If we were to go with this reasoning than maybe we can drop the current OAuth auto-config classes. By the time we release 5.1 we'll have auto-config for resource server as well.

And given that Boot follows Semantic Versioning, you wouldn't be able to drop it until 3.0 which will be much later than when Spring Security 5.1 is released.

@rwinch What are your thoughts on this?

@rwinch
Copy link
Member

rwinch commented Sep 11, 2017

@wilkinsona @jgrandja I think it would be ideal if we could drop the auto configuration of the old OAuth related code. However, I think that may be problematic in regards to our timeline on providing a replacement and the needs of UAA users. Perhaps a better option would be to move the old OAuth auto configuration from Boot to another location (i.e. spring-security-oauth)

@wilkinsona
Copy link
Member

Thanks, both. That's an interesting suggest, @rwinch. I've opened #10255 to have a discussion focussed on this. Could you comment over there too please?

@jgrandja jgrandja force-pushed the security5-oauth2-autoconfig branch 2 times, most recently from b2326a2 to 555d228 Compare September 12, 2017 04:03
@jgrandja
Copy link
Author

@wilkinsona The EnvironmentPostProcessor has been removed. I believe I have addressed all outstanding items. Good to go for another full review.

@jgrandja jgrandja force-pushed the security5-oauth2-autoconfig branch from 6eb5479 to 8f6134d Compare September 13, 2017 15:13
@jgrandja
Copy link
Author

jgrandja commented Sep 13, 2017

@philwebb I added a new commit that avoids adding the client defaults to the Environment. This gives us another option at least.

@jgrandja jgrandja force-pushed the security5-oauth2-autoconfig branch 2 times, most recently from 154580c to eff6888 Compare September 13, 2017 18:44
@philwebb philwebb self-assigned this Sep 18, 2017
@philwebb philwebb added priority: normal type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Sep 18, 2017
@philwebb philwebb added this to the 2.0.0.M5 milestone Sep 18, 2017
Copy link
Member

@snicoll snicoll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see @philwebb assigned himself but I had that review pending that I left off to finalize M4.

Here are some ideas. My biggest complain is about the configuration structure (easy to fix) and the default properties file.

* @author Joe Grandja
* @since 2.0.0
*/
@ConfigurationProperties(prefix = "security.oauth2")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're moving the security configuration to spring.security.* in 2.0. I don't know the scope of the new OAuth2 support but if we have a client support and a resource server support it would be worth splitting things up a bit more.

This was discussed in prior reviews but spring.security.oauth2.client.providers sounds a better name to me. Right now we have no way to define any other client-related property.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change the prefix to spring.security.oauth2.

The scope for 5.0 is strictly Client support and soon after around Mar-Apr 2018 we will bring Resource Server support in 5.1. The idea was to initially house the client properties in OAuth2Properties and then leverage the same for Resource Server properties. Hence the placement of it in the package org.springframework.boot.autoconfigure.security.oauth2 and the prefix of spring.security.oauth2.

I don't feel spring.security.oauth2.client.providers makes sense given that the defined Roles, as per spec: Resource Server, Client, Authorization Server and Resource Owner. The providers define the Resource Server and Authorization Server whereas the properties we are defining here represent the Client role and the attributes of a Client Registration. Therefore, providers may confuse the user since these are client-specific properties.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

providers is just a proposal, that's not important. What is important is that Map is a catch all and we may want to define other client-specific properties in the near future so we can't "steal" the client namespace with the map.

In other words, it should be spring.security.oauth2.client.xyz so that we can reuse the spring.security.oauth2.client namespace for other client-specific settings.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially had the prefix and therefore the namespace as spring.security.oauth2.client but then it didn't quite read right because given the Map<String, ClientRegistrationProperties> clients the binding path would be spring.security.oauth2.client.clients. The namespace spring.security.oauth2.client represents a singular form whereas Spring Security allows for multiple client configurations.

As far as defining other client properties that are Boot specific, then it might make sense to have Boot's own representation of ClientRegistrationProperties that essentially duplicates the one in Spring Security but at least provides the flexibility to create new properties per client that are Boot specific. What do you think?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was just chatting with @rwinch and yes it does make sense to split up OAuth2Properties to OAuth2ClientProperties and OAuth2ResourceServerProperties (future). This will prevent class loading issues as both the client and resource-server modules are optional.

I'll rename OAuth2Properties to OAuth2ClientProperties for now.

return this.clients;
}

public void setClients(Map<String, ClientRegistrationProperties> clients) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need for a setter for a Map if the field is initialized

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok will remove the setter.

*/
final class ClientPropertiesUtil {

private static final String CLIENT_DEFAULTS_RESOURCE_LOCATION = "META-INF/spring-security-oauth2-client-defaults.properties";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, those defaults do not belong in Spring Boot

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can easily move spring-security-oauth2-client-defaults.properties into Spring Security. Please confirm if this is what you would prefer.

@ConfigurationProperties(prefix = "security.oauth2")
public class OAuth2Properties {

private Map<String, ClientRegistrationProperties> clients = new LinkedHashMap<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure I like the idea that we bind a 3rd party class directly to the environment. We've done that in the past and regretted it. It's just a raw observation though, maybe that's fine.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if you would like a new class similar to ClientRegistrationProperties in Boot. Either way, we will keep ClientRegistrationProperties in Spring Security as it serves as a convenience class in certain use cases.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the defaults and how they are applied should largely derive from that. I can certainly appreciate you have an infrastructure in the project that we would reuse. I just don't think binding it directly to the environment is a good idea.

Copy link
Author

@jgrandja jgrandja Sep 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate on a specific issue you had in the past where you used a 3rd party class to bind in the Environment? I would like to understand this more.

.get();

// Override with merged client properties
oauth2Properties.setClients(mergedClients);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this is too low-level.

What if we had a Map<String,Foo> (name TBD) and one attribute of this object would be a the ID of an oauth2 client type (google, github, facebook, etc). What the auto-configuration can then do is apply default values based on the client-type. If the client is fully configured, that's fine and we'll use that but all the properties that can be inferred by the client type are then set.

In Spring Boot we could put something in place so that new "id" can be registered if necessary.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I completely follow? Maybe an example to elaborate would help.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what @snicoll is suggesting is an attribute that specifies the "template" for common properties.

We could have an enum (probably in Spring Security) that defines well known templates:

public enum OAuth2ClientTemplate {

    GOOGLE, FACEBOOK, GITHUB

}

In the client property we then have a "template" field:

public class OAuth2ClientProperties {
    private OAuth2ClientTemplate template;
    private String redirectUrl;
    private String scope;
    // etc
}

The user can then specify the template in the properties file. Some examples:

# Standard GitHub with some keys
spring.security.oauth2.client.mygithub.template=GITHUB
spring.security.oauth2.client.mygithub.token=ZYX

# GitHub but override the scope with some keys
spring.security.oauth2.client.foogithub.template=GITHUB
spring.security.oauth2.client.foogithub.token=ZYX
spring.security.oauth2.client.foogithub.scope=email

# Something completely custom
spring.security.oauth2.client.bar.redirect-uri=...
spring.security.oauth2.client.bar.token=ZYX
spring.security.oauth2.client.barscope=baz

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Let me give this one some thought

Copy link
Member

@snicoll snicoll Sep 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I meant (with a few things we may need to adapt but we shouldn't worry about that now). The main idea is that this mechanism of providing default values should be in Spring Security and therefore the API that allows you to configure your client should be there as well.

That's also a reason why we shouldn't bind Spring Security's API directly on the environment. We need to be in control on what options we expose to the user.

@philwebb philwebb added the status: on-hold We can't start working on this issue yet label Sep 19, 2017
@philwebb
Copy link
Member

I've marked this one as on-hold because we really need to consider #10255 at the same time.

@ConditionalOnClass({EnableWebSecurity.class, ClientRegistration.class})
@ConditionalOnMissingBean(WebSecurityConfigurerAdapter.class)
@ConditionalOnBean(ClientRegistrationRepository.class)
@AutoConfigureBefore(ClientRegistrationRepositoryAutoConfiguration.class)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jgrandja shouldn't this be @AutoConfigureAfter(ClientRegistrationRepositoryAutoConfiguration.class) because that's the one that provides the ClientRegistrationRepository bean? Also, I think for the @ConditionalOnMissingBean(WebSecurityConfigurerAdapter.class) to match, it would need to be auto-configured before SecurityAutoConfiguration so that the default WebSecurityConfigurerAdapter from SpringBootWebSecurityConfiguration does not kick in.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the heads up @mbhave.
Yeah I noticed that today as I was re-working the PR.

I changed it to:

@AutoConfigureBefore(SecurityAutoConfiguration.class)
@AutoConfigureAfter(ClientRegistrationRepositoryAutoConfiguration.class)

I'm going to push this sometime tomorrow after I finish up a couple more things.
Thanks!

@jgrandja jgrandja force-pushed the security5-oauth2-autoconfig branch from eff6888 to 9b25f87 Compare September 21, 2017 10:55
@jgrandja
Copy link
Author

@snicoll @philwebb I've pushed the updates based on all your feedback.

  • Renamed OAuth2Properties -> OAuth2ClientProperties and set prefix to spring.security.oauth2.client
  • Added OAuth2ClientProperties.ClientRegistration - no longer binding to Spring Security's ClientRegistrationProperties
  • Great idea re: OAuth2ClientProperties.ClientRegistration.clientType - this worked out quite nicely
  • Removed defaults properties resource and it now lives in Spring Security, see OAuth2ClientPropertiesUtil

This commit provides auto-configuration for Spring Security 5.0 OAuth 2.0 / OpenID Connect 1.0 client support.
The default auto-configuration will register a ClientRegistrationRepository with the context and
will enable httpSecurity.oauth2Login() based on a number of conditions.
@jgrandja jgrandja force-pushed the security5-oauth2-autoconfig branch from 9b25f87 to 7dc5a72 Compare September 22, 2017 16:37
@mbhave
Copy link
Contributor

mbhave commented Oct 2, 2017

We simplified this a little more as part of #10497. Closing this PR in favor of that.

@mbhave mbhave closed this Oct 2, 2017
@mbhave mbhave added status: declined A suggestion or change that we don't feel we should currently apply and removed status: on-hold We can't start working on this issue yet labels Oct 2, 2017
@snicoll snicoll removed priority: normal type: enhancement A general enhancement labels Oct 3, 2017
@snicoll snicoll removed this from the 2.0.0.M5 milestone Oct 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants