feat: honour JVM proxy system properties in reactive OAuth2 client#100
Merged
Conversation
The `customWebClient` used for OIDC token exchange, userinfo, and refresh-token calls is built on Reactor Netty's `HttpClient`, which does not consult JVM system properties for proxy configuration by default. Customers behind a corporate egress proxy who set the standard `-Dhttps.proxyHost`/`-Dhttp.proxyHost`/`-Dhttp.nonProxyHosts` JVM args (or `HTTPS_PROXY` env vars picked up by their JVM) see those settings honoured by the JDK-based `RestTemplate` paths in this library (OIDC discovery via `ClientRegistrations.fromIssuerLocation`, JWKS fetch via `SimpleRemoteJwkSource`) but silently bypassed by every Reactor Netty call. The result is that login completes the browser-side redirect but hangs on the server-side token exchange callback. Adding `.proxyWithSystemProperties()` to the `HttpClient` builder closes that gap and makes the reactive OAuth2 client consistent with the JDK paths already present in this configuration. The call is a no-op when no proxy properties are set, so customers who do not need a proxy see no behaviour change. Added unit coverage that verifies both behaviours (no proxy props → `hasProxy()` is false; `https.proxyHost`/`https.proxyPort` set → supplier-backed HTTP `ProxyProvider` matches host/port). JIRA: TRIVIAL risk: low
jeskepetr
approved these changes
May 25, 2026
Contributor
jeskepetr
left a comment
There was a problem hiding this comment.
Looks good to me.
Thanks for the fix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The
customWebClientused by Spring Security's reactive OAuth2 client for token exchange, userinfo, and refresh-token calls is built on Reactor Netty'sHttpClient, which does not consult JVM proxy system properties by default. The JDK-basedRestTemplatepaths in this same library do consult them (ClientRegistrations.fromIssuerLocationfor OIDC discovery,SimpleRemoteJwkSourcefor JWKS), creating a partial-proxy behaviour where OIDC discovery and JWKS calls go through a corporate proxy but token/userinfo/refresh calls silently bypass it.Symptom for a customer behind a corporate egress proxy: the browser-side redirect to the IdP completes and credentials work, but the server-side callback (token exchange) hangs or 502s because the auth-service pod cannot reach the IdP's token endpoint directly.
Adding
.proxyWithSystemProperties()to theHttpClientchain closes the gap. The call is a no-op when no proxy system properties are set, so customers who do not configure a proxy see no behaviour change.What changed
gooddata-server-oauth2-autoconfigure/src/main/kotlin/ReactiveCommunicationClientsConfiguration.kt:62-66— one chained call on theHttpClientbuilder, plus a comment explaining the rationale.gooddata-server-oauth2-autoconfigure/src/test/kotlin/ReactiveCommunicationClientsConfigurationTest.kt— new unit test asserting both states (no proxy props ⇒hasProxy()is false;https.proxyHost/https.proxyPortset ⇒ supplier-backed HTTPProxyProvidermatches host/port).Test plan
./gradlew :gooddata-server-oauth2-autoconfigure:test— 261 tests pass (2 new, 259 pre-existing)./gradlew :gooddata-server-oauth2-autoconfigure:detekt :gooddata-server-oauth2-autoconfigure:detektTest— cleangdc-nasauth-service) deploy and smoke-test login flow)Notes on
proxyProviderSuppliervsproxyProviderReactor Netty 1.2.x stores system-property-derived proxies as a
Supplier<ProxyProvider>(lazy) onClientTransportConfig, separate from the eagerProxyProviderfield.hasProxy()is the right boolean check, sinceproxyProvider()alone returnsnulleven when a supplier-backed proxy is configured. The test asserts against both to make this explicit.Risk
risk: low— additive call that is a no-op for customers who do not set JVM proxy system properties. Behaviour for OIDC-only customers without a proxy is unchanged.JIRA: TRIVIAL