Skip to content

Commit c780d65

Browse files
Max BatischevMax Batischev
Max Batischev
authored and
Max Batischev
committed
Add support configuring OAuth2AuthorizationRequestResolver as bean
Closes spring-projectsgh-15236
1 parent 68aef20 commit c780d65

File tree

4 files changed

+96
-12
lines changed

4 files changed

+96
-12
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurer.java

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -58,7 +58,7 @@
5858
* {@link ClientRegistrationRepository} {@code @Bean} may be registered instead.
5959
*
6060
* <h2>Security Filters</h2>
61-
*
61+
* <p>
6262
* The following {@code Filter}'s are populated for {@link #authorizationCodeGrant()}:
6363
*
6464
* <ul>
@@ -67,7 +67,7 @@
6767
* </ul>
6868
*
6969
* <h2>Shared Objects Created</h2>
70-
*
70+
* <p>
7171
* The following shared objects are populated:
7272
*
7373
* <ul>
@@ -76,7 +76,7 @@
7676
* </ul>
7777
*
7878
* <h2>Shared Objects Used</h2>
79-
*
79+
* <p>
8080
* The following shared objects are used:
8181
*
8282
* <ul>
@@ -283,10 +283,12 @@ private OAuth2AuthorizationRequestResolver getAuthorizationRequestResolver() {
283283
if (this.authorizationRequestResolver != null) {
284284
return this.authorizationRequestResolver;
285285
}
286-
ClientRegistrationRepository clientRegistrationRepository = OAuth2ClientConfigurerUtils
287-
.getClientRegistrationRepository(getBuilder());
288-
return new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository,
289-
OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
286+
ResolvableType resolvableType = ResolvableType.forClass(OAuth2AuthorizationRequestResolver.class);
287+
OAuth2AuthorizationRequestResolver bean = getBeanOrNull(resolvableType);
288+
return (bean != null) ? bean
289+
: new DefaultOAuth2AuthorizationRequestResolver(
290+
OAuth2ClientConfigurerUtils.getClientRegistrationRepository(getBuilder()),
291+
OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
290292
}
291293

292294
private OAuth2AuthorizationCodeGrantFilter createAuthorizationCodeGrantFilter(B builder) {

config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -4532,9 +4532,12 @@ private ReactiveClientRegistrationRepository getClientRegistrationRepository() {
45324532
}
45334533

45344534
private OAuth2AuthorizationRequestRedirectWebFilter getRedirectWebFilter() {
4535-
OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter;
4536-
if (this.authorizationRequestResolver != null) {
4537-
return new OAuth2AuthorizationRequestRedirectWebFilter(this.authorizationRequestResolver);
4535+
ServerOAuth2AuthorizationRequestResolver result = this.authorizationRequestResolver;
4536+
if (result == null) {
4537+
result = getBeanOrNull(ServerOAuth2AuthorizationRequestResolver.class);
4538+
}
4539+
if (result != null) {
4540+
return new OAuth2AuthorizationRequestRedirectWebFilter(result);
45384541
}
45394542
return new OAuth2AuthorizationRequestRedirectWebFilter(getClientRegistrationRepository());
45404543
}

config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java

+68-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -285,6 +285,18 @@ public void configureWhenCustomAuthorizationRedirectStrategySetThenAuthorization
285285
verify(authorizationRedirectStrategy).sendRedirect(any(), any(), anyString());
286286
}
287287

288+
@Test
289+
public void configureWhenCustomAuthorizationRequestResolverBeanPresentThenAuthorizationRequestIncludesCustomParameters()
290+
throws Exception {
291+
this.spring.register(OAuth2ClientBeanConfig.class).autowire();
292+
// @formatter:off
293+
this.mockMvc.perform(get("/oauth2/authorization/registration-1"))
294+
.andExpect(status().is3xxRedirection())
295+
.andReturn();
296+
// @formatter:on
297+
verify(authorizationRequestResolver).resolve(any());
298+
}
299+
288300
@EnableWebSecurity
289301
@Configuration
290302
@EnableWebMvc
@@ -362,4 +374,59 @@ OAuth2AuthorizedClientRepository authorizedClientRepository() {
362374

363375
}
364376

377+
@EnableWebSecurity
378+
@Configuration
379+
@EnableWebMvc
380+
static class OAuth2ClientBeanConfig {
381+
382+
@Bean
383+
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
384+
// @formatter:off
385+
http
386+
.authorizeRequests()
387+
.anyRequest().authenticated()
388+
.and()
389+
.requestCache()
390+
.requestCache(requestCache)
391+
.and()
392+
.oauth2Client()
393+
.authorizationCodeGrant()
394+
.authorizationRedirectStrategy(authorizationRedirectStrategy)
395+
.accessTokenResponseClient(accessTokenResponseClient);
396+
return http.build();
397+
// @formatter:on
398+
}
399+
400+
@Bean
401+
ClientRegistrationRepository clientRegistrationRepository() {
402+
return clientRegistrationRepository;
403+
}
404+
405+
@Bean
406+
OAuth2AuthorizedClientRepository authorizedClientRepository() {
407+
return authorizedClientRepository;
408+
}
409+
410+
@Bean
411+
OAuth2AuthorizationRequestResolver authorizationRequestResolver() {
412+
OAuth2AuthorizationRequestResolver defaultAuthorizationRequestResolver = authorizationRequestResolver;
413+
authorizationRequestResolver = mock(OAuth2AuthorizationRequestResolver.class);
414+
given(authorizationRequestResolver.resolve(any()))
415+
.willAnswer((invocation) -> defaultAuthorizationRequestResolver.resolve(invocation.getArgument(0)));
416+
return authorizationRequestResolver;
417+
}
418+
419+
@RestController
420+
class ResourceController {
421+
422+
@GetMapping("/resource1")
423+
String resource1(
424+
@RegisteredOAuth2AuthorizedClient("registration-1") OAuth2AuthorizedClient authorizedClient) {
425+
return "resource1";
426+
}
427+
428+
}
429+
430+
}
431+
365432
}

config/src/test/java/org/springframework/security/config/web/server/OAuth2LoginTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
6565
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
6666
import org.springframework.security.oauth2.client.userinfo.ReactiveOAuth2UserService;
67+
import org.springframework.security.oauth2.client.web.server.DefaultServerOAuth2AuthorizationRequestResolver;
6768
import org.springframework.security.oauth2.client.web.server.ServerAuthorizationRequestRepository;
6869
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizationRequestResolver;
6970
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
@@ -457,6 +458,7 @@ public void oauth2LoginWhenCustomBeansThenUsed() {
457458
OidcUser user = TestOidcUsers.create();
458459
ReactiveOAuth2UserService<OidcUserRequest, OidcUser> userService = config.userService;
459460
given(userService.loadUser(any())).willReturn(Mono.just(user));
461+
ServerOAuth2AuthorizationRequestResolver resolver = config.resolver;
460462
// @formatter:off
461463
webTestClient.get()
462464
.uri("/login/oauth2/code/google")
@@ -466,6 +468,7 @@ public void oauth2LoginWhenCustomBeansThenUsed() {
466468
verify(config.jwtDecoderFactory).createDecoder(any());
467469
verify(tokenResponseClient).getTokenResponse(any());
468470
verify(securityContextRepository).save(any(), any());
471+
verify(resolver).resolve(any());
469472
}
470473

471474
// gh-5562
@@ -837,6 +840,10 @@ static class OAuth2LoginWithCustomBeansConfig {
837840

838841
ServerSecurityContextRepository securityContextRepository = mock(ServerSecurityContextRepository.class);
839842

843+
ServerOAuth2AuthorizationRequestResolver resolver = spy(
844+
new DefaultServerOAuth2AuthorizationRequestResolver(new InMemoryReactiveClientRegistrationRepository(
845+
TestClientRegistrations.clientRegistration().build())));
846+
840847
@Bean
841848
SecurityWebFilterChain springSecurityFilter(ServerHttpSecurity http) {
842849
// @formatter:off
@@ -864,6 +871,11 @@ ReactiveJwtDecoderFactory<ClientRegistration> jwtDecoderFactory() {
864871
return this.jwtDecoderFactory;
865872
}
866873

874+
@Bean
875+
ServerOAuth2AuthorizationRequestResolver resolver() {
876+
return this.resolver;
877+
}
878+
867879
@Bean
868880
ReactiveOAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient() {
869881
return this.tokenResponseClient;

0 commit comments

Comments
 (0)