mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-06 02:48:13 +00:00
fix(proxy): remove x-api-key when OAuth Authorization header is present
When ANTHROPIC_AUTH_TOKEN is set and forward_client_headers is true, Claude Code sends x-litellm-api-key: Bearer <oauth_token>. The proxy forwards this as x-api-key (via ANTHROPIC_API_HEADERS) AND adds Authorization: Bearer <oauth_token> (via OAuth detection). Both headers end up in provider_specific_headers.extra_headers. However, when the Anthropic API receives both x-api-key and Authorization with the same OAuth token value, it uses x-api-key, which fails for OAuth tokens (x-api-key requires sk-ant-api* format, not sk-ant-oat*). Fix: when we detect an OAuth Authorization header, remove x-api-key from the provider-specific headers since it would take precedence at the HTTP level and cause 'Invalid key=value pair' errors. Fixes #24436
This commit is contained in:
parent
b58c1538a4
commit
29f728c089
2 changed files with 39 additions and 0 deletions
|
|
@ -1945,6 +1945,11 @@ def add_provider_specific_headers_to_request(
|
|||
if header.lower() == "authorization" and is_anthropic_oauth_key(value):
|
||||
anthropic_headers[header] = value
|
||||
added_header = True
|
||||
# Remove x-api-key from headers since it's incompatible with OAuth tokens.
|
||||
# When both Authorization and x-api-key are sent with the same token value,
|
||||
# the Anthropic API uses x-api-key (which fails for OAuth format).
|
||||
# We must keep only Authorization for OAuth tokens.
|
||||
anthropic_headers.pop("x-api-key", None)
|
||||
break
|
||||
if added_header is True:
|
||||
# Anthropic headers work across multiple providers
|
||||
|
|
|
|||
|
|
@ -511,6 +511,40 @@ class TestProxyOAuthHeaderForwarding:
|
|||
assert psh["extra_headers"]["authorization"] == f"Bearer {FAKE_OAUTH_TOKEN}"
|
||||
assert psh["extra_headers"]["anthropic-beta"] == "oauth-2025-04-20"
|
||||
|
||||
def test_add_provider_specific_headers_oauth_removes_conflicting_x_api_key(self):
|
||||
"""When both x-api-key and OAuth Authorization are present, x-api-key must be
|
||||
removed to prevent the Anthropic API from preferring it over Authorization.
|
||||
|
||||
Regression test for https://github.com/BerriAI/litellm/issues/24436
|
||||
When ANTHROPIC_AUTH_TOKEN is set and forward_client_headers is true, Claude Code
|
||||
sends x-litellm-api-key: Bearer <oauth_token>. The proxy forwards this as
|
||||
x-api-key (from ANTHROPIC_API_HEADERS). But when we also add
|
||||
Authorization: Bearer <oauth_token>, the Anthropic API uses x-api-key (which
|
||||
fails for OAuth tokens since x-api-key requires sk-ant-api* format).
|
||||
Fix: remove x-api-key when we detect an OAuth Authorization header.
|
||||
"""
|
||||
from litellm.proxy.litellm_pre_call_utils import (
|
||||
add_provider_specific_headers_to_request,
|
||||
)
|
||||
|
||||
data: dict = {}
|
||||
# This is what the proxy receives from Claude Code when ANTHROPIC_AUTH_TOKEN is set:
|
||||
# x-api-key from ANTHROPIC_API_HEADERS + authorization from OAuth detection
|
||||
headers = {
|
||||
"x-api-key": f"Bearer {FAKE_OAUTH_TOKEN}",
|
||||
"authorization": f"Bearer {FAKE_OAUTH_TOKEN}",
|
||||
"content-type": "application/json",
|
||||
}
|
||||
|
||||
add_provider_specific_headers_to_request(data=data, headers=headers)
|
||||
|
||||
assert "provider_specific_header" in data
|
||||
psh = data["provider_specific_header"]
|
||||
assert psh["extra_headers"]["authorization"] == f"Bearer {FAKE_OAUTH_TOKEN}"
|
||||
# x-api-key must NOT be present - it would take precedence over Authorization
|
||||
# at the HTTP level, causing "Invalid key=value pair" errors for OAuth tokens
|
||||
assert "x-api-key" not in psh["extra_headers"]
|
||||
|
||||
def test_clean_headers_forwards_x_api_key_when_authenticated_with_litellm_key(self):
|
||||
"""clean_headers should forward x-api-key when user authenticated with x-litellm-api-key and forward_llm_provider_auth_headers=True."""
|
||||
from starlette.datastructures import Headers
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue