From b7f93a8913e8876cb9f19034ef6c2fff69731d94 Mon Sep 17 00:00:00 2001 From: Dennis Henry Date: Sun, 10 May 2026 16:25:05 -0400 Subject: [PATCH] fix: address greptile review concerns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _types.py: narrow LiteLLM_JWTAuth.issuer from Union[str, List[str]] to str — PyJWT performs strict string equality on the 'iss' claim and silently rejects all tokens when passed a list value - SSOModals.tsx: replace inline provider-detection block with the shared detectSSOProvider() utility (same logic already used in EditSSOSettingsModal.tsx via utils.ts) to prevent the two paths from diverging when new providers are added Co-Authored-By: Claude Sonnet 4.6 --- litellm/proxy/_types.py | 4 ++-- .../src/components/SSOModals.tsx | 18 ++---------------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index beb12abf6b0..b743fa9226c 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -4448,9 +4448,9 @@ class LiteLLM_JWTAuth(LiteLLMPydanticObjectBase): default=None, description="Expected JWT aud claim. Falls back to JWT_AUDIENCE.", ) - issuer: Optional[Union[str, List[str]]] = Field( + issuer: Optional[str] = Field( default=None, - description="Expected JWT iss claim. Falls back to JWT_ISSUER.", + description="Expected JWT iss claim. Falls back to JWT_ISSUER. Must be a single string — PyJWT performs strict string equality on the 'iss' claim.", ) public_allowed_routes: List[str] = ["public_routes"] enforce_rbac: bool = False diff --git a/ui/litellm-dashboard/src/components/SSOModals.tsx b/ui/litellm-dashboard/src/components/SSOModals.tsx index 9f4cce28839..21140e673dc 100644 --- a/ui/litellm-dashboard/src/components/SSOModals.tsx +++ b/ui/litellm-dashboard/src/components/SSOModals.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react"; import { Modal, Form, Input, Button as Button2, Select, Checkbox } from "antd"; import { Text, TextInput } from "@tremor/react"; import { getSSOSettings, updateSSOSettings } from "./networking"; +import { detectSSOProvider } from "./Settings/AdminSettings/SSOSettings/utils"; import NotificationsManager from "./molecules/notifications_manager"; import { parseErrorMessage } from "./shared/errorUtils"; @@ -114,22 +115,7 @@ const SSOModals: React.FC = ({ try { const ssoData = await getSSOSettings(accessToken); if (ssoData && ssoData.values) { - // Determine which SSO provider is configured - let selectedProvider = null; - if (ssoData.values.google_client_id) { - selectedProvider = "google"; - } else if (ssoData.values.microsoft_client_id) { - selectedProvider = "microsoft"; - } else if (ssoData.values.okta_client_id) { - selectedProvider = "okta"; - } else if (ssoData.values.generic_client_id) { - // Backward compatibility: older Okta UI settings were stored as generic OIDC endpoints. - if (ssoData.values.generic_authorization_endpoint?.includes("okta")) { - selectedProvider = "okta"; - } else { - selectedProvider = "generic"; - } - } + const selectedProvider = detectSSOProvider(ssoData.values); // Extract role mappings if they exist let roleMappingFields = {};