🤖 feat: add Azure Entra ID keyless auth for OpenAI provider#2428
🤖 feat: add Azure Entra ID keyless auth for OpenAI provider#2428ibetitsmike wants to merge 4 commits intomainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2e0c3b7e2
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (codexOauthRequired && !storedCodexOauth && !creds.isConfigured) { | ||
| // fall back to their API key instead of blocking entirely. If no API key | ||
| // exists, surface the OAuth setup requirement. | ||
| if (codexOauthRequired && !storedCodexOauth && !creds.apiKey) { |
There was a problem hiding this comment.
Allow Entra fallback for Codex-required models
createModel now returns oauth_not_connected whenever a Codex-required model has no stored OAuth and no creds.apiKey, which also blocks OpenAI configs that are otherwise configured via Entra (authMode=entra + baseUrl). In that scenario resolveProviderCredentials reports configured credentials, but this guard exits before Entra fallback is evaluated, so requests for required Codex models fail immediately despite the new keyless auth path being present.
Useful? React with 👍 / 👎.
| init?: Parameters<typeof fetch>[1] | ||
| ): Promise<Response> => { | ||
| const tokenProvider = await getEntraBearerTokenProvider(); | ||
| const token = await tokenProvider(); |
There was a problem hiding this comment.
Propagate AbortSignal into Entra token acquisition
wrapFetchWithOpenAIEntraAuth calls tokenProvider() without passing through init.signal, so request cancellation cannot interrupt DefaultAzureCredential token acquisition. When identity endpoints are slow or unreachable, users can abort the chat request in the UI but this auth step will still block until credential timeouts complete, which breaks expected cancellation behavior.
Useful? React with 👍 / 👎.
Summary
Adds Azure Entra ID (Microsoft identity) keyless authentication as a new auth path for the OpenAI provider. Enterprise Azure deployments can now use
DefaultAzureCredential(viaaz login, managed identity, or workload identity) instead of distributing API keys.Background
Enterprise customers deploying Azure OpenAI often rely on Azure Entra ID for authentication rather than API keys. This enables tighter security controls (no long-lived secrets), compliance with corporate identity policies, and seamless integration with Azure managed identity on cloud workloads.
The implementation reuses the existing
openaiprovider namespace — no new provider or model migration needed. Auth priority is preserved: API key → Codex OAuth → Entra keyless → error.Implementation
Core auth flow (
providerModelFactory.ts):@azure/identity(DefaultAzureCredential+getBearerTokenProvider)Authorization: Bearer <token>and removex-api-keyheaderCredential resolver (
providerRequirements.ts):authMode=entra+baseUrlpresent, no API key requiredproviders.jsonc) and env vars (OPENAI_AUTH_MODE=entra+OPENAI_BASE_URL)Schema + service (
api.ts,providerService.ts):openaiAuthMode: "apiKey" | "entra"field toProviderConfigInfoSchemaUI (
ProvidersSection.tsx):updateOptimisticallypersistence patternDocs (
providers.mdx,gen_docs.ts):OPENAI_AUTH_MODEin env var tableValidation
make static-check— all checks pass (typecheck, lint, fmt, docs links, eager imports)Risks
@azure/identityis lazily loaded only whenauthMode=entra— no impact on non-Azure users (no startup cost, no bundle bloat for users who don't use it)DefaultAzureCredentialsurface when credentials are missing.Generated with
mux• Model:anthropic:claude-opus-4-6• Thinking:xhigh• Cost:$1.20