Skip to content

Make it easier to create an integration test for an OAuth2 resource server #44906

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
dsyer opened this issue Mar 26, 2025 · 4 comments
Closed
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@dsyer
Copy link
Member

dsyer commented Mar 26, 2025

If you want to integration test a resource server you need the OAuth2 client, but when you add that (even just in test scope) it changes the security configuration of a Spring Boot application by default - it is no longer a resource server, but instead it becomes an OAuth2 client (and installs an OAuth2 login filter instead of the resource server filter).

Also, it's kind of a pain to set up a RestClient with a bearer token for the test. You have to create an interceptor. With client credentials it looks like this:

@Bean
@Lazy
public RestClient personService(RestClient.Builder builder, ClientRegistrationRepository repository,
		OAuth2AuthorizedClientService service,
		@Value("http://localhost:${local.server.port:8080}") String url) {
	AuthorizedClientServiceOAuth2AuthorizedClientManager manager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(
			repository, service);
	OAuth2ClientHttpRequestInterceptor interceptor = new OAuth2ClientHttpRequestInterceptor(manager);
	interceptor.setClientRegistrationIdResolver(request -> "spring");
	builder.baseUrl(url).requestInterceptor(interceptor);
	return builder.build();
}

Ideally we'd like a way to tell Spring Boot that to set that stuff up: 1) switch off the OAuth2SecurityFilterChainConfiguration (currently not visible and not an independent autoconfig, so you can't actually exclude it); 2) make it easier to create an HTTP client.

Sort of related to #43978 but this is for a webapp that is itself a resource server.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Mar 26, 2025
@wilkinsona
Copy link
Member

switch off the OAuth2SecurityFilterChainConfiguration (currently not visible and not an independent autoconfig, so you can't actually exclude it)

Do you lose too much if you exclude org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration?

make it easier to create an HTTP client

Isn't that a job for Spring Security? I don't see anything Boot-specific about the boilerplate above.

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label Apr 16, 2025
@dsyer
Copy link
Member Author

dsyer commented Apr 16, 2025

Excluding the OAuth2ClientAutoconfiguration leads to other issues because I still have a client.

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

OAuth2ClientAutoconfiguration is an @Import of 2 separate classes and I guess I need one of them.

Actually, having tried it, it turns out I need parts of both for my RestClient to work as above:

		@Bean
		@ConditionalOnMissingBean(ClientRegistrationRepository.class)
		InMemoryClientRegistrationRepository clientRegistrationRepository(OAuth2ClientProperties properties) {
			List<ClientRegistration> registrations = new ArrayList<>(
					new OAuth2ClientPropertiesMapper(properties).asClientRegistrations().values());
			return new InMemoryClientRegistrationRepository(registrations);
		}

		@Bean
		@ConditionalOnMissingBean
		OAuth2AuthorizedClientService authorizedClientService(
				ClientRegistrationRepository clientRegistrationRepository) {
			return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
		}

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 16, 2025
@wilkinsona
Copy link
Member

wilkinsona commented Apr 16, 2025

It looks like we're suffering a bit as the class path's a poor signal for what you want due to Spring Security having its client-side OAuth2 client support and its server-side OAuth2 client support in the same jar. That means we need a better signal or to at least split things up a bit so that you can use excludes to manually get what you want.

We auto-configure 4 beans:

  • InMemoryClientRegistrationRepository
  • OAuth2AuthorizedClientService
  • OAuth2AuthorizedClientRepository
  • SecurityFilterChain

InMemoryClientRegistrationRepository and OAuth2AuthorizedClientService are used on both sides while OAuth2AuthorizedClientRepository and SecurityFilterChain are server-specific. I think we need to restructure the auto-configuration to reflect this. Maybe OAuth2ClientAutoConfiguration for the pieces that are used on both sides and OAuth2ClientWebAutoConfiguration (not sure about this name) for the server-specific pieces.

We also have the same problem on the reactive side with ReactiveOAuth2ClientAutoConfiguration.

When we split things up, we should think about the package names too.

OAuth2ClientAutoConfiguration is in org.springframework.boot.autoconfigure.security.oauth2.client.servlet at the moment. That package might make sense for OAuth2ClientWebAutoConfiguration but there's nothing servlet-specific about InMemoryClientRegistrationRepository and OAuth2AuthorizedClientService so it won't really make sense for the revised OAuth2ClientAutoConfiguration.

On the reactive side, ReactiveOAuth2ClientAutoConfiguration is in org.springframework.boot.autoconfigure.security.oauth2.client.reactive which isn't as bad as it doesn't imply web application in the same way that servlet does.

There's quite a bit of overlap with #40997.

@wilkinsona wilkinsona added for: team-meeting An issue we'd like to discuss as a team to make progress and removed status: feedback-provided Feedback has been provided labels Apr 16, 2025
@wilkinsona wilkinsona self-assigned this Apr 17, 2025
@wilkinsona wilkinsona 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 Apr 22, 2025
@wilkinsona wilkinsona modified the milestones: 3.5.x, 3.5.0-RC1 Apr 22, 2025
@wilkinsona
Copy link
Member

231396e has split things up. @dsyer, you should now be able to exclude org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientWebSecurityAutoConfiguration which will disable to OAuth 2 Client based web security and keep org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration that auto-configures the general OAuth 2 Client beans.

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

3 participants