From 2b4c0544033d687fe77e83177e2c6cc07ea15253 Mon Sep 17 00:00:00 2001 From: Tin Chi Lo Date: Fri, 10 Jul 2026 15:47:05 -0700 Subject: [PATCH] feat(ui): move the dcr_bridge toggle next to the OAuth app fields Render DcrBridgeToggle inside PassthroughAuthorizeSection, after the OAuth client ID/secret fields and just before the Authorize & Fetch Tools button, in both the create and edit flows. Also update the section copy to say a configured OAuth app is saved with the server, using the same wording as the credential lifecycle rework in #32752 so whichever PR lands second rebases cleanly --- .../mcp_tools/PassthroughAuthorizeSection.tsx | 32 +++++++++++-------- .../mcp_tools/create_mcp_server.test.tsx | 19 +++++++++-- .../mcp_tools/create_mcp_server.tsx | 4 +-- .../mcp_tools/mcp_server_edit.test.tsx | 13 ++++++++ .../components/mcp_tools/mcp_server_edit.tsx | 2 -- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/ui/litellm-dashboard/src/components/mcp_tools/PassthroughAuthorizeSection.tsx b/ui/litellm-dashboard/src/components/mcp_tools/PassthroughAuthorizeSection.tsx index af81f2713ae..998fcd2ebf8 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/PassthroughAuthorizeSection.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/PassthroughAuthorizeSection.tsx @@ -1,5 +1,6 @@ import React from "react"; import { Button, Form, Input } from "antd"; +import DcrBridgeToggle from "./DcrBridgeToggle"; import { isClientForwardedTokenMode } from "./types"; interface PassthroughOAuthFlow { @@ -11,20 +12,23 @@ interface PassthroughOAuthFlow { /** * Browser-only Authorize & Fetch for the client-forwarded token modes - * (true_passthrough / oauth_delegate). LiteLLM never stores upstream - * credentials for these modes, so the token obtained here lives in this - * browser session only: it is forwarded per-server for the tools preview and - * allowlist configuration, and is never written to the server row or the - * per-user credential store. The optional client credentials cover IdPs - * without dynamic client registration (e.g. a pre-registered Slack app) and - * ride the temporary authorize session only. + * (true_passthrough / oauth_delegate). Tokens are never stored: the token + * obtained here lives in this browser session only, forwarded per-server for + * the tools preview and allowlist configuration, and is never written to the + * server row or the per-user credential store. The optional OAuth client + * credentials cover IdPs without dynamic client registration (e.g. a + * pre-registered Slack app); unlike the token they ARE saved onto the server + * as declared config, so internal users' Authorize relays through the org's + * app instead of dead-ending on upstreams that cannot mint clients. */ export default function PassthroughAuthorizeSection({ authType, oauthFlow, + dcrBridgeInitialChecked, }: { authType?: string | null; oauthFlow: PassthroughOAuthFlow; + dcrBridgeInitialChecked?: boolean; }) { if (!isClientForwardedTokenMode(authType)) return null; const authorizeButtonLabels: Record = { @@ -35,14 +39,15 @@ export default function PassthroughAuthorizeSection({ return (

- Callers bring their own upstream token for this auth type, so LiteLLM stores no upstream credentials. To preview - tools and configure the tool allowlist, authorize against the upstream here: the token stays in this browser - session only and is never saved to LiteLLM. + Callers bring their own upstream token for this auth type, so LiteLLM never stores tokens. To preview tools and + configure the tool allowlist, authorize against the upstream here: the token stays in this browser session only + and is never saved to LiteLLM. An OAuth app configured below IS saved with the server, so internal users who + authorize from the Tools page go through it.

OAuth Client ID (optional, not saved)} + label={OAuth Client ID (optional, saved)} name={["credentials", "client_id"]} - extra="Only needed when the upstream does not support dynamic client registration (e.g. a pre-registered Slack app). Used for this browser authorization only." + extra="Set this to make everyone authorize through a specific app; required for upstreams without dynamic client registration (e.g. a pre-registered Slack app)." > OAuth Client Secret (optional, not saved)} + label={OAuth Client Secret (optional, saved)} name={["credentials", "client_secret"]} > +