fix(mcp): strip duplicate delegated credentials

This commit is contained in:
Joshua Valluru 2026-09-12 17:18:54 -07:00
parent 97b964dd9a
commit 364e466210
3 changed files with 59 additions and 8 deletions

View file

@ -1083,7 +1083,9 @@ def _should_strip_caller_authorization(
has_explicit_litellm_admission_header: Final = _has_explicit_litellm_admission_header(raw_headers)
if is_delegated_oauth:
return not has_explicit_litellm_admission_header
return not has_explicit_litellm_admission_header or _authorization_is_litellm_admission_credential(
raw_headers, user_api_key_auth
)
return _authorization_is_litellm_admission_credential(raw_headers, user_api_key_auth) or (
user_api_key_auth is None and not has_explicit_litellm_admission_header
)
@ -1110,15 +1112,11 @@ def _authorization_is_litellm_admission_credential(
That is the case when no usable ``x-litellm-api-key`` was sent, or when the client repeated the
same key in both headers.
"""
if user_api_key_auth is None or not user_api_key_auth.api_key:
return False
admission_header: Final = _raw_header_value(raw_headers, "x-litellm-api-key")
if not admission_header:
return True
authorization: Final = _raw_header_value(raw_headers, "authorization")
return authorization is not None and strip_auth_scheme(authorization, "Bearer") == strip_auth_scheme(
admission_header, "Bearer"
)
if admission_header and authorization:
return strip_auth_scheme(authorization, "Bearer") == strip_auth_scheme(admission_header, "Bearer")
return bool(user_api_key_auth and user_api_key_auth.api_key and not admission_header)
def _format_byok_openapi_auth_header(mcp_server: MCPServer, mcp_auth_header: str) -> str:

View file

@ -578,6 +578,36 @@ def test_prepare_mcp_server_headers_legacy_delegate_preserves_separate_upstream_
assert extra_headers == {"Authorization": "Bearer upstream-token"}
def test_prepare_mcp_server_headers_legacy_delegate_strips_repeated_admission_key():
from litellm.proxy._experimental.mcp_server.server import (
_prepare_mcp_server_headers,
)
from litellm.proxy._types import UserAPIKeyAuth
server = MCPServer(
server_id="legacy-delegate-repeated-key",
name="legacy-delegate",
transport=MCPTransport.http,
auth_type=MCPAuth.oauth2,
delegate_auth_to_upstream=True,
)
server_auth_header, extra_headers = _prepare_mcp_server_headers(
server=server,
mcp_server_auth_headers=None,
mcp_auth_header=None,
oauth2_headers={"Authorization": "Bearer sk-litellm-key"},
raw_headers={
"x-litellm-api-key": "Bearer sk-litellm-key",
"authorization": "Bearer sk-litellm-key",
},
user_api_key_auth=UserAPIKeyAuth(api_key="sk-litellm-key"),
)
assert server_auth_header is None
assert extra_headers is None
def test_prepare_mcp_server_headers_m2m_skips_authorization_from_raw_extra_headers():
"""M2M must not merge caller Authorization from raw_headers when extra_headers lists it."""
try:

View file

@ -3433,6 +3433,29 @@ class TestMCPServerManager:
)
assert extra_headers == {"Authorization": "Bearer upstream-token"}
@pytest.mark.asyncio
async def test_call_regular_mcp_tool_legacy_delegate_strips_repeated_admission_key(self):
from litellm.proxy._types import UserAPIKeyAuth
server = MCPServer(
server_id="server-legacy-delegate-repeated-key",
name="legacy-delegate",
url="https://example.com",
transport=MCPTransport.http,
auth_type=MCPAuth.oauth2,
delegate_auth_to_upstream=True,
)
extra_headers = await self._capture_call_extra_headers(
server,
oauth2_headers={"Authorization": "Bearer sk-litellm-key"},
raw_headers={
"x-litellm-api-key": "Bearer sk-litellm-key",
"authorization": "Bearer sk-litellm-key",
},
user_api_key_auth=UserAPIKeyAuth(api_key="sk-litellm-key"),
)
assert not extra_headers or "authorization" not in {k.lower() for k in extra_headers}
def test_should_strip_caller_authorization_new_modes(self):
from litellm.proxy._types import UserAPIKeyAuth