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).
Comment From: wilkinsona
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.
Comment From: thake
@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.
Comment From: wilkinsona
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
Comment From: mbhave
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.