feat(auth): add X.509 workload identity federation - #864
Conversation
HAYDEN-OAI
left a comment
There was a problem hiding this comment.
Two issues need attention before this is safe to ship: X.509 clients currently accept plaintext API endpoints, exposing transferable service-account bearer tokens, and the 401 refresh path resets the configured transient retry budget. Details and concrete reproductions are inline.
HAYDEN-OAI
left a comment
There was a problem hiding this comment.
The previous HTTPS enforcement and shared retry-budget findings are fixed. One separate backward-compatibility regression remains in legacy workload-identity refresh timing; details and a concrete timing example are inline.
| val newExpiry = Instant.now().plusSeconds(expiresIn.toLong()) | ||
| val expiresAfterNanos = TimeUnit.SECONDS.toNanos(expiresIn.toLong()) | ||
| val configuredBufferNanos = max(0L, config.refreshBuffer.toNanos()) | ||
| val effectiveBufferNanos = min(configuredBufferNanos, expiresAfterNanos / 2) |
There was a problem hiding this comment.
[P2] Preserve configured refresh timing for existing JWT/ID-token identities
This half-lifetime clamp runs for every workload identity, although it is documented only for the new X.509 builder. Existing WorkloadIdentity.builder().refreshBufferSeconds(...) clients previously refreshed at exactly expiry - refreshBufferSeconds; for a one-hour JWT/ID-token lease with refreshBufferSeconds(3000), refresh used to begin after 600 seconds but now silently begins after 1800 seconds. That 20-minute delay breaks the existing public configuration contract and can leave long-running requests or downstream token consumers without their deliberately configured expiration margin. Apply the half-TTL clamp only when isX509, preserving the configured refresh threshold for legacy subject-token identities.
What and why
Implement Phase 1 (HTTP only) of X.509 Workload Identity Federation in OpenAI SDKs — Design Proposal. Applications that already own a mutually authenticated HTTP transport can exchange their X.509 workload identity for short-lived OpenAI access tokens without configuring a subject-token provider or exposing certificate material through SDK options.
Public API and Java idioms
@JvmStatic WorkloadIdentity.x509Builder()fluent builder; the existingbuilder()binary signature and JWT/ID-token builder remain unchanged.Duration, existing SDK builders, existingHttpClient, canonical retry/backoff machinery,ReentrantLock, and Java 8-compatibleCompletableFuturerather than introducing another transport or concurrency framework.https://mtls.api.openai.com/v1; preserves explicit URLs,withOptions()semantics, synchronous/asynchronous parity, Spring wiring, and Kotlin consumers.OPENAI_AUTH_MODE=api_key|x509rollout example and README guidance.Security, transport, and certificate ownership
POST https://mtls.auth.openai.com/oauth/token; its JSON structurally omitssubject_token, and there is no custom public exchange URL.HttpClient; JSSE/the native transport retain sole ownership of certificates, private keys, passphrases, trust managers, proxies, HSMs, pools, executors, and certificate rotation.expires_in, cache against monotonic time, clamp refresh buffers to half the token TTL, deduplicate sync/async refreshes, protect shared refreshes from waiter cancellation, and honor bounded retry/backoff includingRetry-After.Validation matrix
env JAVA_HOME=/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home ./scripts/formatenv JAVA_HOME=/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home ./scripts/lintenv JAVA_HOME=/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home ./scripts/build— all modules/packages, build-logic tests, Jackson compatibility, generated test classes, and support-policy checks.env JAVA_HOME=/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home ./scripts/test— 12,074 tests, 0 failures, 0 errors across the complete generated-mock-backed repository suite, including ProGuard/R8 and existing API-key/JWT/ID-token regressions../scripts/detect-breaking-changes fcdcc7ee0414bbd92284a0839c0b7a6997cf8415— baseline and proposed public API compatibility.:openai-java-runtime-compatibility:runRuntimeCompatibilityfor every declared runtime: Java 8, 11, 17, 21, 25, and 26; exercises all four published artifacts: core, OkHttp, aggregate SDK, and Bedrock.javacand confirmed major bytecode version 52.subject_token, redirect refusal, full client certificate chain on both network legs, trust/transport ownership, bounded transient retry andRetry-After, sync/async single flight, mixed sync/async concurrency, cancellation-safe waiters, monotonic expiry/refresh clamp, proactive refresh, stale-token invalidation, repeatable/non-repeatable request-body replay, one-retry limits, secret redaction,withOptions()rebinding, and existing API-key plus JWT/ID-token behavior.Compatibility and scope
API-key authentication and existing JWT/ID-token workload federation retain their existing endpoints, token payloads, defaults, and retry conventions.
HttpRequest.followRedirects()is additive and defaults to existing behavior. All supported Java runtimes, Java/Kotlin builder compatibility, caller-owned transports, and conventional Spring configuration remain supported.Realtime/WebSockets are explicitly excluded and deferred to Phase 2.