feat: add TransportOptions for configuring TLS, proxy, and default headers#122
feat: add TransportOptions for configuring TLS, proxy, and default headers#122
Conversation
Introduce a TransportOptions class that encapsulates transport-level configuration (defaultHeaders, caCertPath, insecure, proxyUrl). Factory methods now have overloads accepting TransportOptions alongside the existing signatures for backward compatibility. Internal auth plumbing (OpenId, builders) refactored to use TransportOptions throughout.
There was a problem hiding this comment.
Pull request overview
Adds a reusable TransportOptions object to configure transport-layer behavior (custom CA certs, insecure TLS, proxy routing, and default headers) and threads it through Zitadel client factory methods, authenticators, OpenID discovery, and the API HTTP client.
Changes:
- Introduce
TransportOptions(+ builder) and new Zitadel factory overloads accepting it. - Apply transport options to OpenID discovery (
OpenId) and to API calls via Apache HttpClient (ApiClient). - Add README “Advanced Configuration” examples and a new integration-style test suite for transport options.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/java/com/zitadel/TransportOptions.java | New immutable options object + builder for headers, proxy, TLS flags, and CA cert path. |
| src/main/java/com/zitadel/Zitadel.java | Add factory overloads/constructors that accept TransportOptions and build ApiClient with it. |
| src/main/java/com/zitadel/ApiClient.java | Build Apache HttpClient with proxy, default headers, and TLS customization based on TransportOptions. |
| src/main/java/com/zitadel/auth/OpenId.java | Apply proxy/TLS/default headers during OpenID discovery request. |
| src/main/java/com/zitadel/auth/OAuthAuthenticator.java | Thread TransportOptions into builder construction (via OpenId), plus add a setter. |
| src/main/java/com/zitadel/auth/ClientCredentialsAuthenticator.java | Add builder overload accepting TransportOptions. |
| src/main/java/com/zitadel/auth/WebTokenAuthenticator.java | Add overloads accepting TransportOptions for JSON-based construction and builder creation. |
| src/test/java/com/zitadel/TransportOptionsTest.java | New Testcontainers/WireMock-based test coverage for transport options scenarios. |
| README.md | Document transport options usage patterns and examples. |
| spotbugs.xml | Add suppressions related to intentional insecure TLS and broad exception handling in transport setup. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When a custom CA certificate is configured, the previous implementation created an empty KeyStore and only added the custom cert, which dropped all JVM default trust anchors. This meant connections to hosts using publicly-trusted certificates would fail. Now the default trusted certs are loaded into the KeyStore alongside the custom CA.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Use a pre-generated keystore with proper SANs (localhost, 127.0.0.1, ::1) for WireMock HTTPS instead of extracting certs at runtime. This fixes the hostname mismatch error on systems where localhost resolves to IPv6. Also threads transport options through to OAuth token exchange requests so that custom CA, insecure mode, proxy, and default headers apply end-to-end.
Fix testProxyUrl to actually call withClientCredentials, add testTransportOptionsObject test, and add proxy credential support.
Default to TransportOptions.defaults() when null is passed, consistent with all other SDK entry points.
OpenId, OAuthAuthenticator, and OAuthAuthenticatorBuilder now default to TransportOptions.defaults() when null is passed, consistent with all other SDKs.
Fail fast with IllegalArgumentException when null or blank header name or null value is passed to defaultHeader().
Extract duplicated SSL context construction from OAuthAuthenticator, OpenId, and ApiClient into TransportOptions.buildSSLContext().
Add WireMock stub for settings endpoint and use WireMock's /__admin/requests/count API to assert custom headers are sent on actual API calls, not just during initialization.
Remove unnecessary @SuppressFBWarnings annotation from getToken. Change proxy test to use withAccessToken instead of withClientCredentials since WireMock cannot act as an HTTP proxy for OpenID discovery.
Build the SSLContext once on first use and cache it using double-checked locking. This avoids repeated disk reads of the CA cert file and redundant keystore construction on every token request.
The installation section incorrectly showed the PHP composer command instead of the Maven dependency XML block.
The PATH_TRAVERSAL_IN suppression is no longer needed on the public caching wrapper since the file I/O moved to buildSSLContextInternal.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 12 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add <removeUnusedImports/> to the Spotless Maven plugin config so unused imports are automatically stripped during formatting.
Leftover imports from when SSL/TLS code was moved to TransportOptions.
Description
This pull request adds support for transport options, allowing users to configure custom CA certificates, disable TLS verification for development environments, route requests through HTTP proxies, and inject default headers (e.g.
Proxy-Authorization) into all SDK requests. A newTransportOptionsclass bundles these four settings into a single reusable object that can be passed to any factory method (withAccessToken,withClientCredentials,withPrivateKey). The existing method signatures are unchanged — the new overloads withTransportOptionsare purely additive, no breaking changes.Related Issue
N/A
Motivation and Context
Users deploying Zitadel behind corporate proxies, firewalls, or in environments with self-signed or private CA certificates had no clean way to configure these transport-level settings. This change gives them a single object they can construct once with their proxy URL, CA cert path, TLS preferences, and any extra headers, then pass it to whichever authentication method they use.
How Has This Been Tested
TransportOptionsTest) verifies custom CA certs, insecure mode, default headers, proxy URLs, and the failure case when connecting to HTTPS without a trusted cert — all usingTransportOptionsobjects passed towithClientCredentials.Documentation
The README has been updated with transport options examples under Advanced Configuration showing
TransportOptions.Builderusage for each setting.Checklist