GA Does Not Mean One Credential
OpenAI's API changelog marked mutual TLS and X.509 workload identity federation generally available on August 29, 2026. The useful security change is precise: a workload can exchange its verified certificate identity for a short-lived OpenAI access token instead of keeping a long-lived API key.
The X.509 workload identity guide also defines the boundary that is easy to miss. The API call still carries two credentials: an ordinary bearer token and a client certificate accepted by the current API mTLS policy. They are authorized independently. The bearer is not cryptographically bound to the exchange certificate through DPoP or a cnf claim, so a token minted with certificate A can be used with certificate B when B independently passes the applicable mTLS policy.
A certificate without a bearer does not authorize the API call. A bearer without an accepted certificate does not cross an active mTLS boundary. Your rollout evidence must show both failures, not merely show that one happy-path request returned 2xx.
Build the Fixture in a Non-Critical Project
Create a disposable project and service account. Upload a test root under Mutual TLS, activate it only for that project, and issue two valid client chains from the root: client-a for token exchange and client-b for the independent-certificate case. Also issue or retain one chain from an untrusted root. Keep every private key in a temporary secret store and delete the fixture after retaining redacted results.
Configure one X.509 provider that derives a stable, non-empty openai.subject from a certificate fact such as a dedicated DNS SAN. Create a mapping from the exact derived value to the disposable service account and grant only the API permissions needed by the canary. X.509 mappings match derived openai.* attributes, not raw JWT claims such as sub, iss, or aud. Record the provider ID, service-account ID, root fingerprint, activation scope, mapped subject, permission set, mTLS host, and one small API request.
Before changing authentication, apply the inventory method from the AI authentication migration plan: trace issuer, verifier, store, runtime injection, API client, renewal loop, and administrative recovery. Keep private keys behind the workload boundary described in the zero-trust architecture guide for AI agents; neither the article's test log nor application telemetry should contain keys, certificates, or access tokens.
Exchange Once, Then Record the Lifetime
The exchange endpoint is the exact POST https://mtls.auth.openai.com/oauth/token. Present the certificate chain and private key in TLS. Send the identity-provider and service-account identifiers in the JSON body, but do not copy certificate material or invent a subject_token field. The chain file must put the leaf first and include any required intermediates because OpenAI does not retrieve missing intermediates from AIA URLs.
curl --cert "$CLIENT_A_CHAIN" \
--key "$CLIENT_A_KEY" \
--request POST "https://mtls.auth.openai.com/oauth/token" \
--header "Content-Type: application/json" \
--data @- <<JSON
{
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token_type": "urn:openai:params:oauth:token-type:x509",
"identity_provider_id": "${OPENAI_IDENTITY_PROVIDER_ID}",
"service_account_id": "${OPENAI_SERVICE_ACCOUNT_ID}"
}
JSON
Store the returned access_token without printing it. Record expires_in and scope separately. OpenAI says the token lasts at most one hour and never outlives the certificate used for exchange; the response can therefore be shorter than an illustrative 3,600 seconds. There is no refresh token. Renewal repeats the certificate exchange, so test that loop before the first token expires rather than discovering it during a live request.
Run the Pass/Fail Matrix
Use the exact API host and surface the workload will call. OpenAI documents default, US, and EU mTLS hosts, but route and model availability may differ. Capture timestamp, case ID, certificate fingerprint, token issue time, status, and response error code. Redact the bearer and certificate contents. The matrix passes only when every row matches its intended class:
| Case | Bearer | Client certificate | Expected evidence |
|---|---|---|---|
| A: baseline | Current token | Accepted A | Canary succeeds with the mapped service account's permissions |
| B: missing certificate | Current token | None | Fails the active mTLS policy; capture certificate_required when returned |
| C: missing bearer | None | Accepted A | Fails normal API authentication |
| D: independent certificate | Token minted with A | Accepted B | Succeeds, proving the bearer is not certificate-bound |
| E: untrusted chain | Current token | Untrusted | Fails certificate path verification |
| F: expired bearer | Expired token | Accepted A | Fails bearer authentication while certificate admission remains valid |
| G: mapping mismatch | Exchange attempted | Valid but unmapped subject | Exchange fails; no API token is available |
| H: denied permission | Current limited token | Accepted A | Allowed canary succeeds; a deliberately ungranted API action fails |
Do not flatten all failures into "authentication failed." OpenAI publishes certificate error codes including certificate_required, invalid_certificate, certificate_verification_failed, and certificate_attribute_verification_failed. Token exchange intentionally exposes more generic OAuth failures. Preserve the body so operators can distinguish certificate admission, provider or mapping resolution, bearer validity, and service-account permissions.
Test Activation Before You Trust It
An uploaded root is not enough; the relevant certificate must be active at the intended scope. OpenAI checks active project-level certificates before organization-level certificates, and if neither scope has an active certificate, mTLS adds no certificate check. That makes case B a deployment gate: a request without a certificate must fail after activation. If it succeeds, stop. The traffic is not traversing the policy you think you enabled.
Run the same negative probe from the real workload network and SDK path. A test laptop calling the correct host cannot prove that production changed from api.openai.com to mtls.api.openai.com. Record the resolved base URL and keep the host configuration outside application business logic so rollback changes one controlled setting.
Rehearse Rotation With Overlap
The OpenAI mTLS guide gives a recovery-safe trust-anchor sequence: upload the new root without deactivating the old one, activate it at every intended scope, move workloads to chains under the new root, test each host and API surface, then deactivate the old root. Delete the old certificate object only after it is inactive for the organization and every project.
Turn that sequence into a drill. While both roots are active, prove old and new client chains pass. Move the exchange client and API client independently, rerun cases A through H, and then deactivate the old root. Prove the old chain fails and the new chain stays green. Your rollback before old-root deactivation is to restore the old workload chain. Your rollback after deactivation is to reactivate the old root and restore the old chain, provided the old private material remains uncompromised and within validity.
Intermediate rotation is narrower: the configured root can stay in place, but clients must present the new complete chain on later exchanges and API calls. Include one missing-intermediate negative probe so a TLS library that silently sent an incomplete chain cannot reach production.
Revocation Requires Your Own Kill Path
OpenAI states that it does not perform certificate revocation list or OCSP checks in this flow. Treat CA revocation as an internal signal, not as proof that OpenAI will immediately reject the certificate. The operational kill path is therefore a combination of mTLS root deactivation or rotation, provider and mapping controls, service-account permissions, and the short lifetime of bearer tokens already issued.
Document which control contains each incident. If one leaf key is exposed under a shared root, rotating or deactivating the root may affect other workloads; a narrowly matched CEL certificate filter, provider condition, or mapping may offer a smaller blast radius, depending on what was compromised. If the root key is exposed, prepare the overlapping new-root path first where risk permits, move clean workloads, and remove the old trust path. Never promise that deleting a mapping instantly invalidates a bearer already issued; the source documents emphasize the short token lifetime, so measure the residual window and make it part of the incident record.
The Production Gate Is Recoverable Failure
Promote the design only when the baseline succeeds, every negative row fails for the intended reason, renewal happens before expiry, the least-privilege permission test is selective, and both sides of the root-rotation drill work. The runbook must name an owner who can change certificate activation, an owner who can change provider or mapping configuration, the token cache location, the maximum measured residual token lifetime, the host rollback setting, and the last known-good root fingerprint.
The durable result is not "we removed the API key." It is a tested boundary with two observable credentials, a mapping you can explain, an expiry loop you have watched renew, and a recovery path that still works when either certificate trust or bearer authorization is deliberately broken.