Skip to content

feat(ui): configure OpenAI workload identity federation from the LLM Credentials and Add Model forms - #45528

Merged
mateo-berri merged 3 commits into
mainfrom
litellm_openai_wif_dashboard_ui
Oct 9, 2026
Merged

mateo-berri merged 3 commits into
mainfrom
litellm_openai_wif_dashboard_ui

Conversation

@mateo-berri

@mateo-berri mateo-berri commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • The proxy supports OpenAI workload identity federation, but the Admin UI cannot configure it
  • LLM Credentials and Add Model always demand an OpenAI API key

How it solves it:

  • OpenAI gets the Authentication selector Anthropic credentials already have
  • Federation swaps API Key for Identity Provider ID, Service Account ID, Identity Token File
  • Under federation, API Base must be api.openai.com or a regional *.api.openai.com host
  • Add Model offers "Use workload identity federation" for OpenAI too
  • Federated OpenAI credentials show a "Workload identity federation" badge

User Flow

Before: a proxy admin cannot set up a keyless OpenAI credential from the Admin UI, because every OpenAI form asks for an API key

  1. The admin opens https://litellm-domain/ui/models-and-endpoints/, clicks the LLM Credentials tab, clicks Add Credential, and picks OpenAI
  2. The form shows only API Base, Organization, and a required API Key, with no Authentication selector
  3. Clicking Add Credential with no key shows "Required" under API Key, so nothing is saved
  4. On the Add Model tab, picking OpenAI offers no "Use workload identity federation" button, only the same required API Key

Before 1: OpenAI credential form has no Authentication selector

Before 2: Add Credential with no key shows Required

Before 3: Add Model with OpenAI only offers the API key

After: the admin picks workload identity federation once, saves a keyless OpenAI credential, and attaches it to a model

  1. The admin opens https://litellm-domain/ui/models-and-endpoints/, clicks the LLM Credentials tab, clicks Add Credential, and picks OpenAI
  2. An Authentication selector now appears; picking "Workload identity federation" swaps API Key for Identity Provider ID, Service Account ID, and Identity Token File
  3. Clicking Add Credential sends POST https://litellm-domain/credentials with only those values and no api_key, and the row shows a "Workload identity federation" badge
  4. An API Base outside https://api.openai.com or https://*.api.openai.com is refused under federation, while the API key method still accepts any base
  5. On the Add Model tab, picking OpenAI shows "Use workload identity federation", which saves the credential and attaches it to the new model

After 1: Authentication selector on the OpenAI credential form

After 2: federation fields replace the API key

After 3: saved credential row with the federation badge

After 4: non-OpenAI API Base refused under federation

After 5: switching to API key clears the API Base error

After 6: Use workload identity federation on Add Model

After 7: Service Account ID cleared in Edit Credential

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • The handful of test files covering my change pass locally, e.g. uv run pytest tests/unit/<your_test_file>.py -v. Leave the suites (make test-unit-*, make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more
  • My PR passes all required CI/CD checks (e.g., lint, schema.d.ts sync check, etc.)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Each leg ran from its own worktree against a fresh Postgres DB, with no OPENAI_* env vars set and throwaway admin creds. The UI screenshots are the ones under User Flow

# qa_config.yaml
model_list: []
general_settings:
  master_key: os.environ/LITELLM_MASTER_KEY
LITELLM_MODE=PRODUCTION STORE_MODEL_IN_DB=True DATABASE_URL=postgresql://...@127.0.0.1:5432/litellm_qa45528_<leg> \
  python litellm/proxy/proxy_cli.py --config qa_config.yaml --port 34008 --num_workers 2 --use_v2_migration_resolver
cd ui/litellm-dashboard && NEXT_PUBLIC_BASE_URL=http://localhost:34008 npx next dev -p 43111

Before (145d382)

Add a keyless OpenAI credential

  1. Open http://localhost:43111/models-and-endpoints/, click LLM Credentials, then Add Credential, name it qa-openai-wif, and pick Provider OpenAI
  2. The form shows API Base (https://api.openai.com/v1), OpenAI Organization ID and OpenAI API Key, with no Authentication selector (Before 1)
  3. Click Add Credential with the key empty: "Required" shows under OpenAI API Key and the dialog stays open (Before 2)

API Base check under federation

  1. The form from the previous case has no Authentication selector, so federation and its API Base check can't be picked

Attach the credential on Add Model

  1. On the Add Model tab, pick Provider OpenAI, LiteLLM Model Name gpt-6.1-sol and Public Model Name qa-gpt-wif
  2. Only API Base, OpenAI Organization ID and the OpenAI API Key show, with no "Use workload identity federation" button (Before 3)

Edit a federated credential

  1. No keyless OpenAI credential can be saved (first case), so there is nothing to edit

After (b179751)

Add a keyless OpenAI credential

  1. Open http://localhost:43111/models-and-endpoints/, click LLM Credentials, then Add Credential, name it qa-openai-wif, and pick Provider OpenAI
  2. An Authentication selector shows "API key", with the options "API key" and "Workload identity federation" (After 1)
  3. Pick "Workload identity federation": API Key is replaced by Identity Provider ID, Service Account ID and Identity Token File, under a note that the proxy only federates when OPENAI_API_KEY is unset in its environment (After 2)
  4. Fill idp_qa_placeholder, svc_qa_placeholder and a token file path, then click Add Credential. The toast reads "Credential added successfully" and the browser sent:
    POST http://localhost:34008/credentials
    {"credential_name":"qa-openai-wif","credential_values":{"openai_identity_provider_id":"idp_qa_placeholder","openai_service_account_id":"svc_qa_placeholder","openai_identity_token_file":"<scratch>/qa_token/token"},"credential_info":{"custom_llm_provider":"OpenAI"}}
    
  5. The table row reads qa-openai-wif | OpenAI | Workload identity federation (After 3)

API Base check under federation

  1. Click Add Credential, name it qa-openai-apibase, pick OpenAI and "Workload identity federation", set API Base to https://gateway.example.com/v1 and Service Account ID to svc_qa_placeholder, then click Add Credential
  2. API Base turns red with "Workload identity federation only reaches the OpenAI API. Enter https://api.openai.com/v1 or a regional *.api.openai.com URL, or leave this empty", the dialog stays open, and no request is sent (After 4)
  3. Switch Authentication to "API key": the error clears right away and API Base keeps the gateway URL (After 5)
  4. Enter OpenAI API Key sk-not-real and click Add Credential. The toast reads "Credential added successfully" and the browser sent no federation fields:
    POST http://localhost:34008/credentials
    {"credential_name":"qa-openai-apibase","credential_values":{"api_base":"https://gateway.example.com/v1","api_key":"sk-not-real"},"credential_info":{"custom_llm_provider":"OpenAI"}}
    

Attach the credential on Add Model

  1. On the Add Model tab, pick Provider OpenAI, LiteLLM Model Name gpt-6.1-sol and Public Model Name qa-gpt-wif
  2. Below OpenAI API Key it reads "Workload identity federation is saved as a credential, then attached to this model." next to a "Use workload identity federation" button (After 6)
  3. Pick qa-openai-wif under Existing Credentials and click Add Model. The toast reads "Model qa-gpt-wif created successfully" and the browser sent:
    POST http://localhost:34008/model/new
    {"model_name":"qa-gpt-wif","litellm_params":{"model":"gpt-6.1-sol","custom_llm_provider":"openai","litellm_credential_name":"qa-openai-wif"},"model_info":{}}
    
  4. The proxy has the model wired to the credential:
    $ curl -s http://localhost:34008/model/info -H "Authorization: Bearer $LITELLM_MASTER_KEY"
    ... "model_name": "qa-gpt-wif", "litellm_params": {"custom_llm_provider": "openai", "litellm_credential_name": "qa-openai-wif", "model": "gpt-6.1-sol", ...}
    

Edit a federated credential

  1. Edit qa-openai-wif: it opens on "Workload identity federation" with the saved values and the token file masked as /p****en
  2. Clear Service Account ID and click Update Credential. The toast reads "Credential updated successfully" and the browser sent (After 7):
    PATCH http://localhost:34008/credentials/qa-openai-wif
    {"credential_name":"qa-openai-wif","credential_values":{},"credential_info":{"custom_llm_provider":"OpenAI"},"credential_values_to_delete":["openai_service_account_id"]}
    
  3. Reopening it shows Service Account ID empty and the other values unchanged

Surprises:

  • Proxy started from the worktree root loads that .env (leaves it alone)
  • Dev overlay shows a React uncontrolled-to-controlled input warning (leaves it alone: comes from the untouched provider inputs)

PASS

Type

New Feature

Caveats (if any)

Medium

  • Federation only kicks in when the proxy has no OPENAI_API_KEY env var
    • With that var set, the proxy sends the key and ignores the credential's federation values
    • The form says so above the federation fields

Low

  • API Base shows https://api.openai.com/v1 prefilled, but the prefill is only sent once edited (pre-existing)

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Note

Medium Risk
Changes credential form payloads and auth-method inference for stored secrets; mistakes could mis-label credentials or send wrong federation fields, but scope is UI-only with broad integration tests.

Overview
Adds OpenAI workload identity federation to the Admin UI by generalizing the Anthropic-only federation flow into shared credential_federation helpers that cover Anthropic and OpenAI.

LLM Credentials and Add Model now show the Authentication selector (API key vs workload identity federation) for OpenAI. Federation hides the API key and collects OpenAI-specific fields (identity provider ID, service account ID, identity token file), with copy explaining federation applies when OPENAI_API_KEY is unset on the proxy. Under federation, API Base is validated to https://api.openai.com (or regional *.api.openai.com); API key mode still allows custom bases.

AnthropicFederationFields becomes FederationFields with provider-specific sections; patch/create logic and federated detection move into credential_federation. The credentials table’s federated badge uses inferAuthMethod so only credentials without a stored API key count as federated (including OpenAI). Add Model’s “Use workload identity federation” entry point is gated with federatedProviderOf (OpenAI/Anthropic only, not OpenAI Compatible).

Reviewed by Cursor Bugbot for commit b179751. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps

greptile-apps Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[Medium impact] Adds OpenAI workload identity federation UI to credential and model forms.

Complete and document the required live, unmocked UI QA before merging

Findings

  1. P2 Live QA proof is missing ▶

Summary

Adds OpenAI workload identity federation to LLM Credentials and Add Model, with federation fields, API Base checks, and a Federated badge

  • OpenAI credentials can use workload identity federation instead of an API key.
  • Proxy admins can choose OpenAI federation while adding a model.
  • The credentials table marks OpenAI federation credentials.

Reviews (3) · Last reviewed commit: "fix(ui): clear the federation API Base e..." · Reviewed by Greptile

Comment thread ui/litellm-dashboard/src/components/model_add/openai_federation.ts Outdated
Comment thread ui/litellm-dashboard/src/components/model_add/openai_federation.ts
@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai

Comment thread ui/litellm-dashboard/src/components/model_add/openai_federation.ts
<ProviderSpecificFields
selectedProvider={selectedProvider}
hiddenFieldKeys={selection.authMethod === "federation" ? API_KEY_FIELDS : NO_HIDDEN_FIELDS}
fieldValidators={providerFieldValidators(selection)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Live QA proof is missing

The PR describes pending QA, not completed results. Repository rules require live, unmocked UI testing against a real proxy. Supply that proof before merging

Rule Used: Flag if the PR has no proof of e2e testing (if e2e testing is applicable here. If it's like an AGENTS.md change or something then probably no need to have e2e test proof) that either doesn't exist, claims that the box that it was trying to run in doe... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Live QA proof is now in the PR body: before at 145d382 and after at b179751, with screenshots and the captured request bodies

@mateo-berri

Copy link
Copy Markdown
Contributor Author

@greptileai

@mateo-berri

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: API Base check misses leading whitespace
    • The OpenAI federation API Base validator now rejects leading-whitespace URLs so a pasted padded value cannot save while the proxy skips keyless auth.

Create PR

Or push these changes by commenting:

@cursor push 1f708f385b
Preview (1f708f385b)
diff --git a/ui/litellm-dashboard/src/components/model_add/openai_federation.test.ts b/ui/litellm-dashboard/src/components/model_add/openai_federation.test.ts
--- a/ui/litellm-dashboard/src/components/model_add/openai_federation.test.ts
+++ b/ui/litellm-dashboard/src/components/model_add/openai_federation.test.ts
@@ -30,6 +30,7 @@
     "https://evilapi.openai.com/v1",
     "https://openai.com/v1",
     "https://gateway.example.com/v1",
+    " https://api.openai.com/v1",
     "api.openai.com/v1",
     "not a url",
   ])("refuses %s, which the proxy rejects for workload identity federation", (apiBase) => {

diff --git a/ui/litellm-dashboard/src/components/model_add/openai_federation.ts b/ui/litellm-dashboard/src/components/model_add/openai_federation.ts
--- a/ui/litellm-dashboard/src/components/model_add/openai_federation.ts
+++ b/ui/litellm-dashboard/src/components/model_add/openai_federation.ts
@@ -36,7 +36,7 @@
   hostname === OPENAI_API_HOST || hostname.endsWith(`.${OPENAI_API_HOST}`);
 
 const targetsOpenAIApi = (apiBase: string): boolean => {
-  const url = URL.canParse(apiBase) ? new URL(apiBase) : null;
+  const url = apiBase === apiBase.trimStart() && URL.canParse(apiBase) ? new URL(apiBase) : null;
   return url?.protocol === "https:" && isOpenAIApiHost(url.hostname);
 };

You can send follow-ups to the cloud agent here.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b179751. Configure here.

export const validateOpenAIFederationApiBase = (value: unknown): string | true =>
typeof value !== "string" || isBlank(value) || targetsOpenAIApi(value)
? true
: `Workload identity federation only reaches the OpenAI API. Enter https://${OPENAI_API_HOST}/v1 or a regional *.${OPENAI_API_HOST} URL, or leave this empty`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API Base check misses leading whitespace

Low Severity

validateOpenAIFederationApiBase treats a leading-whitespace OpenAI URL as valid because the URL parser strips that space, but api_base is stored untrimmed. The proxy parses the raw string and then skips federation, so a pasted URL with a leading space saves while keyless auth never runs.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b179751. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proxy still federates here: _targets_openai_api(' https://api.openai.com/v1') returns True since urlparse strips leading spaces. Untrimmed API Base is pre-existing for every auth method

@mateo-berri
mateo-berri enabled auto-merge (squash) October 9, 2026 07:23
@mateo-berri
mateo-berri merged commit a3236ba into main Oct 9, 2026
90 checks passed
@mateo-berri
mateo-berri deleted the litellm_openai_wif_dashboard_ui branch October 9, 2026 07:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants