Skip to content
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

Disable user details auto-configuration if the application has resource server, saml, or oauth2-client dependencies #35338

Closed
thake opened this issue May 8, 2023 · 4 comments
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@thake
Copy link

thake commented May 8, 2023

Description of the Bug

A warning appears on startup when configuring an OAuth2 Resource Server for an MVC application with an individual jwkSetUri programmatically (e.g., not using the default spring boot property).

Configuration

Taken directly from https://docs.spring.io/spring-security/reference/5.8/servlet/oauth2/resource-server/jwt.html#oauth2resourceserver-jwt-jwkseturi-dsl:

@EnableWebSecurity
@Configuration
class SecurityConfiguration {
	@Bean
	fun securityChain(http: HttpSecurity) : SecurityFilterChain {
		http {
			authorizeRequests {
				authorize(anyRequest, authenticated)
			}
			oauth2ResourceServer {
				jwt {
					jwkSetUri = "https://idp.example.com/.well-known/jwks.json"
				}
			}
		}
		return http.build()
	}
}

Warning

2023-05-08T07:09:36.642+02:00  WARN 3586168 --- [           main] .s.s.UserDetailsServiceAutoConfiguration : 

Using generated security password: bb3ffeca-0899-413b-89a8-5869721248c9

This generated password is for development use only. Your security configuration must be updated before running your application in production.

It seems that the UserDetailsServiceAutoConfiguration is wrongfully activated.

Example repo

I've created a repository with a small example project to demonstrate the issue. This issue is present in spring boot 2.7.x (main branch of example repo) and spring boot 3.x (spring boot 3 branch of example repo).

@thake thake changed the title UserDetailsServiceAutoConfiguration is wrongfully activated if jwtkSetUri is set programmatically. UserDetailsServiceAutoConfiguration is wrongfully activated if jwtkSetUri is set programmatically for MVC application. May 8, 2023
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 8, 2023
@wilkinsona
Copy link
Member

Thanks for the example project. It defines the following Spring Security beans:

org.springframework.security.authentication.DefaultAuthenticationEventPublisher
org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$DefaultPasswordEncoderAuthenticationManagerBuilder
org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$EnableGlobalAuthenticationAutowiredConfigurer
org.springframework.security.config.annotation.authentication.configuration.InitializeAuthenticationProviderBeanManagerConfigurer
org.springframework.security.config.annotation.authentication.configuration.InitializeUserDetailsBeanManagerConfigurer
org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor
org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration
org.springframework.security.config.annotation.web.builders.HttpSecurity
org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration
org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration
org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration
org.springframework.security.config.crypto.RsaKeyConversionServicePostProcessor
org.springframework.security.context.DelegatingApplicationListener
org.springframework.security.provisioning.InMemoryUserDetailsManager
org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler
org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator
org.springframework.security.web.DefaultSecurityFilterChain
org.springframework.security.web.FilterChainProxy
org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor

Unfortunately, I don't think there are any beans of a type that indicates that the user details service isn't needed.

When using the equivalent properties-based configuration, the following beans are defined:

org.springframework.security.authentication.DefaultAuthenticationEventPublisher
org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$DefaultPasswordEncoderAuthenticationManagerBuilder
org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$EnableGlobalAuthenticationAutowiredConfigurer
org.springframework.security.config.annotation.authentication.configuration.InitializeAuthenticationProviderBeanManagerConfigurer
org.springframework.security.config.annotation.authentication.configuration.InitializeUserDetailsBeanManagerConfigurer
org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor
org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration
org.springframework.security.config.annotation.web.builders.HttpSecurity
org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration
org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration
org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration
org.springframework.security.config.crypto.RsaKeyConversionServicePostProcessor
org.springframework.security.context.DelegatingApplicationListener
org.springframework.security.oauth2.jwt.NimbusJwtDecoder
org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler
org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator
org.springframework.security.web.DefaultSecurityFilterChain
org.springframework.security.web.FilterChainProxy
org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor

The auto-configured NimbusJwtDecoder causes the auto-configuration of the user details service to back off.

@wilkinsona wilkinsona added the for: team-meeting An issue we'd like to discuss as a team to make progress label May 9, 2023
@thake
Copy link
Author

thake commented May 10, 2023

@wilkinsona, thanks for your analysis!

I've configured the project as documented in the spring security documentation: https://docs.spring.io/spring-security/reference/5.8/servlet/oauth2/resource-server/jwt.html#oauth2resourceserver-jwt-jwkseturi-dsl

Is the documentation missing information that NimbusJwtDecoder needs to be registered manually? In our productive system OAuth2 authentication worked without registering a NimbusJwtDecoder, but we got the annoying warning message described in the first comment, which seemed to be a false positive.

@wilkinsona
Copy link
Member

wilkinsona commented May 10, 2023

Is the documentation missing information that NimbusJwtDecoder needs to be registered manually?

No, I don't think so.

Spring Security offers multiple ways of doing the same thing. You can set the jwkSetUri directly as you have done or you can provide a JwtDecoder bean that's configured with the jwkSetUri. Spring Boot's auto-configuration takes the latter approach which allows UserDetailsServiceAutoConfiguration to back off.

we got the annoying warning message described in the first comment, which seemed to be a false positive.

While we figure out what we can do to fix this, you should be able to work around it by adding the following to application.properties:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration

@mbhave
Copy link
Contributor

mbhave commented May 26, 2023

We are going to look into backing off if resource-server, spring-security-saml or oauth2-client are on the classpath. It seems unlikely that anyone using these dependencies would rely on an InMemoryUserDetailsManager given that it's not recommended for production usage. In case anyone needs one, they can configure the bean themselves.

@mbhave mbhave added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged for: team-meeting An issue we'd like to discuss as a team to make progress labels May 26, 2023
@mbhave mbhave added this to the 3.2.x milestone May 26, 2023
@mbhave mbhave changed the title UserDetailsServiceAutoConfiguration is wrongfully activated if jwtkSetUri is set programmatically for MVC application. Disable UserDetailsServiceAutoConfiguration if the application has resource server, saml, or oauth2-client dependencies May 26, 2023
@philwebb philwebb changed the title Disable UserDetailsServiceAutoConfiguration if the application has resource server, saml, or oauth2-client dependencies Disable UserDetailsServiceAutoConfiguration if the application has resource server, saml, or oauth2-client dependencies Sep 11, 2023
@wilkinsona wilkinsona self-assigned this Sep 18, 2023
@wilkinsona wilkinsona modified the milestones: 3.2.x, 3.2.0-RC1 Sep 26, 2023
@wilkinsona wilkinsona changed the title Disable UserDetailsServiceAutoConfiguration if the application has resource server, saml, or oauth2-client dependencies Disable user details auto-configuration if the application has resource server, saml, or oauth2-client dependencies Sep 26, 2023
wilkinsona added a commit that referenced this issue Dec 13, 2023
There are some notable differences in the behavior of Spring
Security's reactive and servlet-based web security. Notably,
Servlet-based web security (`@EnableWebSecurity`) works without
any authentication manager, rejecting requests as not authorized.
By contrast reactive-based web security (`@EnableWebFluxSecurity`)
fails to start up when there's no authentication manager, either
provided directly as a bean or derived from a
ReactiveUserDetailsService. There are also further differences at
runtime where empty Monos from all ReactiveAuthenticationManagers
results in an internal error and a 500 response whereas a similar
situation in the servlet implementation results in a 401.

Previously, to accommodate these differences in behavior, Spring
Boot's auto-configuration would behave differently. In the Servlet
case, web security would be enabled whenever the necessary
dependencies were on the classpath. In the reactive case, web
security would back off in the absence of an authentication manager
to prevent a start up failure. While this difference is rooted in
Spring Security, it is undesirable and something that we want to
avoid Spring Boot users being exposed to where possible.
Unfortunately, the situation is more likely to occur than before
as ReactiveUserDetailsServiceAutoConfiguration now backs off more
readily (gh-35338). This makes it more likely that the context will
contain neither a reactive authetication manager not a reactive
user details service.

This commit reworks the auto-configurations related to reactive
security. ReactiveSecurityAutoConfiguration will now auto-configure
an "empty" reactive authentication manager that denies access through
Mono.error in the absence of a ReactiveAuthenticationManager,
ReactiveUserDetailsService, or SecurityWebFilterChain. The last of
these is to allow for the situation where a filter chain has been
defined with an authentication manager configured directly on it.
This configuration of an authentication manager allows
`@EnableWebFluxSecurity` to be auto-configured more readily,
removing one of the differences between reactive- and Servlet-based
security.

Corresponding updates to the auto-configurations for reactive OAuth2
support have also been made. They no longer try to auto-configure
`@EnableWebFluxSecurity`, relying instead upon
ReactiveSecurityAutoConfiguration, which they are ordered before, to
do that instead.

Closes gh-38713
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

4 participants