Hi, this is a first-timers-only issue. This means we've worked to make it more legible to folks who either haven't contributed to our codebase before, or even folks who haven't contributed to open source before.

If that's you, we're interested in helping you take the first step and can answer questions and help you out as you do. Note that we're especially interested in contributions from people from groups underrepresented in free and open source software!

If you have contributed before, consider leaving this one for someone new, and looking through our general ideal-for-contribution issues. Thanks!

Problem

When setting up an OAuth2 resource server with multi-tenancy (e.g., the one from the example https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/resource-server/multi-tenancy ), none of the conditions for disabling the UserDetailsServiceAutoConfiguration are met and therefore, an InMemoryUserDetailsManager, which logs the default password, is auto-configured:

2021-06-01 18:34:39.832  INFO 26857 --- [           main] .s.s.UserDetailsServiceAutoConfiguration : 

Using generated security password: f89a4c05-3b75-4c2c-89a0-60dceba7e4ec

Solution

UserDetailsServiceAutoConfiguration should be conditional on missing beans of type org.springframework.security.authentication.AuthenticationManagerResolver as well. The code for UserDetailsServiceAutoConfiguration can be found here. Along with the code, please add tests to ensure the UserDetailsServiceAutoConfiguration backs off in the presence of an AuthenticationManagerResolver bean. Here's an example of a similar test.

Steps to Fix

  • [ ] Claim this issue with a comment below and ask any clarifying questions you need
  • [ ] Set up a repository locally following the Contributing Guidelines
  • [ ] Try to fix the issue following the steps above
  • [ ] Commit your changes and start a pull request.

Comment From: mbhave

@SamuelBucheliZ So there isn't a bean for JwtDecoder or OpaqueTokenIntrospector in this case? I think it would make sense to back off on AuthenticationManagerResolver.

@jzheaux thoughts?

Comment From: SamuelBucheliZ

@mbhave Exactly, in the example, there are no beans for JwtDecoder or OpaqueTokenIntrospector. In the multi-tenancy example I linked above, the problem could be fixed by just adding a @Bean notation e.g., for the JwtDecoder, but this would be a bit of a hack.

However, in general, the problem cannot always be solved so easily. For example, in the use case of supporting multiple issuer URIs, one would typically use JwtIssuerAuthenticationManagerResolver. In this case, obtaining a JwtDecoder bean is not as straightforward (respectively, creating one is still possible with a little bit of effort, but even more of a hack, as this bean wouldn't be used in any place).

For reference, the corresponding code (adapted from the example), would look something like this

@EnableWebSecurity
public class OAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Value("${tenantOne.issuer-uri}")
    String tenantOneIssuerUri;

    @Value("${tenantTwo.issuer-uri}")
    String tenantTwoIssuerUri;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .authorizeRequests((requests) -> requests
                    .mvcMatchers("/**/message/**").hasAuthority("SCOPE_message:read")
                    .anyRequest().authenticated()
            )
            .oauth2ResourceServer((resourceServer) -> resourceServer
                    .authenticationManagerResolver(multitenantAuthenticationManager())
            );
        // @formatter:on
    }

    @Bean
    AuthenticationManagerResolver<HttpServletRequest> multitenantAuthenticationManager() {
        return new JwtIssuerAuthenticationManagerResolver(
                  tenantOneIssuerUri,
                  tenantTwoIssuerUri
            );
    }

}

Comment From: jzheaux

I agree that this bean supersedes creating a UserDetailsService.

Since the purpose of an AuthenticationManagerResolver is to produce an AuthenticationManager, it makes sense to me to apply the same conditional as is done for AuthenticationManager.

ReactiveUserDetailsServiceAutoConfiguration should likely be updated in the same way.

Comment From: nandishkotadia

I am interested in picking this up. Can I work on the same? @scottfrederick @mbhave

Comment From: mbhave

@nandishkotadia Sorry I missed this comment. Are you still interested in working on this issue?

Comment From: bartoszJaszczak

Hi, Is this issue still free? Can I work on it? @mbhave @nandishkotadia EDIT: As I see no pull request on it and no responses to previous post, I will pick it up :) I hope it won't be a problem.

Comment From: mbhave

Closing in favor of PR #28361.

Comment From: qavid

Hi @mbhave, ReactiveUserDetailsServiceAutoConfiguration should be updated in the same way as already mentioned by @jzheaux. Could you please reopen issue?

Comment From: philwebb

@qavid I've opened a new issue to track this https://github.com/spring-projects/spring-boot/issues/31317