1010import java .util .Optional ;
1111import lombok .RequiredArgsConstructor ;
1212import lombok .extern .slf4j .Slf4j ;
13+ import org .springframework .beans .factory .annotation .Qualifier ;
1314import org .springframework .boot .autoconfigure .condition .ConditionalOnProperty ;
1415import org .springframework .boot .autoconfigure .security .oauth2 .client .OAuth2ClientProperties ;
1516import org .springframework .boot .autoconfigure .security .oauth2 .client .OAuth2ClientPropertiesMapper ;
@@ -62,10 +63,14 @@ public class OAuthSecurityConfig extends AbstractAuthSecurityConfig {
6263
6364 /**
6465 * WebClient configured to use system proxy properties (-Dhttps.proxyHost, -Dhttps.proxyPort).
66+ * Created as a bean to ensure system properties are read after context initialization.
6567 */
66- private final WebClient proxyAwareWebClient = WebClient .builder ()
67- .clientConnector (new ReactorClientHttpConnector (HttpClient .create ().proxyWithSystemProperties ()))
68- .build ();
68+ @ Bean (name = "oauthWebClient" )
69+ public WebClient oauthWebClient () {
70+ return WebClient .builder ()
71+ .clientConnector (new ReactorClientHttpConnector (HttpClient .create ().proxyWithSystemProperties ()))
72+ .build ();
73+ }
6974
7075 @ Bean
7176 public SecurityWebFilterChain configure (
@@ -102,34 +107,34 @@ public SecurityWebFilterChain configure(
102107
103108 @ Bean
104109 public ReactiveOAuth2AccessTokenResponseClient <OAuth2AuthorizationCodeGrantRequest >
105- authorizationCodeTokenResponseClient () {
110+ authorizationCodeTokenResponseClient (@ Qualifier ( "oauthWebClient" ) WebClient webClient ) {
106111 var client = new WebClientReactiveAuthorizationCodeTokenResponseClient ();
107- client .setWebClient (proxyAwareWebClient );
112+ client .setWebClient (webClient );
108113 return client ;
109114 }
110115
111116 @ Bean
112117 @ Primary
113- public ReactiveJwtDecoder jwtDecoder () {
118+ public ReactiveJwtDecoder jwtDecoder (@ Qualifier ( "oauthWebClient" ) WebClient webClient ) {
114119 String jwkSetUri = getJwkSetUri ();
115120 if (jwkSetUri == null ) {
116121 return token -> Mono .error (new IllegalStateException ("JWT decoder not configured" ));
117122 }
118123 log .info ("Configuring JWT decoder with JWKS URI: {}" , jwkSetUri );
119- return NimbusReactiveJwtDecoder .withJwkSetUri (jwkSetUri ).webClient (proxyAwareWebClient ).build ();
124+ return NimbusReactiveJwtDecoder .withJwkSetUri (jwkSetUri ).webClient (webClient ).build ();
120125 }
121126
122127 @ Bean
123128 @ Primary
124- public ReactiveOpaqueTokenIntrospector opaqueTokenIntrospector () {
129+ public ReactiveOpaqueTokenIntrospector opaqueTokenIntrospector (@ Qualifier ( "oauthWebClient" ) WebClient webClient ) {
125130 var config = getOpaqueTokenConfig ();
126131 if (config == null ) {
127132 return token -> Mono .error (new IllegalStateException ("Opaque token introspector not configured" ));
128133 }
129134 log .info ("Configuring opaque token introspector with URI: {}" , config .getIntrospectionUri ());
130135 return new SpringReactiveOpaqueTokenIntrospector (
131136 config .getIntrospectionUri (),
132- proxyAwareWebClient .mutate ()
137+ webClient .mutate ()
133138 .defaultHeaders (h -> h .setBasicAuth (config .getClientId (), config .getClientSecret ()))
134139 .build ());
135140 }
@@ -156,9 +161,10 @@ public ReactiveOAuth2UserService<OidcUserRequest, OidcUser> customOidcUserServic
156161 }
157162
158163 @ Bean
159- public ReactiveOAuth2UserService <OAuth2UserRequest , OAuth2User > customOauth2UserService (AccessControlService acs ) {
164+ public ReactiveOAuth2UserService <OAuth2UserRequest , OAuth2User > customOauth2UserService (
165+ AccessControlService acs , @ Qualifier ("oauthWebClient" ) WebClient webClient ) {
160166 final DefaultReactiveOAuth2UserService delegate = new DefaultReactiveOAuth2UserService ();
161- delegate .setWebClient (proxyAwareWebClient );
167+ delegate .setWebClient (webClient );
162168
163169 return request -> delegate .loadUser (request )
164170 .flatMap (user -> {
0 commit comments