mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
fix(anthropic): detect oauth Authorization header case-insensitively
This commit is contained in:
parent
c449f11451
commit
2068066d69
2 changed files with 28 additions and 9 deletions
|
|
@ -78,8 +78,8 @@ def optionally_handle_anthropic_oauth(headers: dict, api_key: str | None) -> tup
|
|||
"""
|
||||
Handle Anthropic OAuth token detection and header setup.
|
||||
|
||||
If an OAuth token is detected in the Authorization header, extracts it
|
||||
and sets the required OAuth headers.
|
||||
If an OAuth token is detected in the Authorization header (any casing),
|
||||
extracts it and sets the required OAuth headers.
|
||||
|
||||
Args:
|
||||
headers: Request headers dict
|
||||
|
|
@ -89,16 +89,18 @@ def optionally_handle_anthropic_oauth(headers: dict, api_key: str | None) -> tup
|
|||
Tuple of (updated headers, api_key)
|
||||
"""
|
||||
# Check Authorization header (passthrough / forwarded requests)
|
||||
auth_header: Final = headers.get("authorization", "")
|
||||
if auth_header and auth_header.startswith(f"Bearer {ANTHROPIC_OAUTH_TOKEN_PREFIX}"):
|
||||
api_key = auth_header.replace("Bearer ", "")
|
||||
headers.pop("x-api-key", None)
|
||||
auth_header: Final = next((value for name, value in headers.items() if name.lower() == "authorization"), "")
|
||||
if auth_header.startswith(f"Bearer {ANTHROPIC_OAUTH_TOKEN_PREFIX}"):
|
||||
api_key = auth_header.removeprefix("Bearer ")
|
||||
for name in tuple(header_name for header_name in headers if header_name.lower() == "x-api-key"):
|
||||
headers.pop(name)
|
||||
headers["anthropic-beta"] = _merge_beta_headers(headers.get("anthropic-beta"), ANTHROPIC_OAUTH_BETA_HEADER)
|
||||
headers["anthropic-dangerous-direct-browser-access"] = "true"
|
||||
return headers, api_key
|
||||
# Check api_key directly (standard chat/completion flow)
|
||||
if api_key and api_key.startswith(ANTHROPIC_OAUTH_TOKEN_PREFIX):
|
||||
headers.pop("x-api-key", None)
|
||||
for name in tuple(header_name for header_name in headers if header_name.lower() == "x-api-key"):
|
||||
headers.pop(name)
|
||||
headers["authorization"] = f"Bearer {api_key}"
|
||||
headers["anthropic-beta"] = _merge_beta_headers(headers.get("anthropic-beta"), ANTHROPIC_OAUTH_BETA_HEADER)
|
||||
headers["anthropic-dangerous-direct-browser-access"] = "true"
|
||||
|
|
|
|||
|
|
@ -31,13 +31,14 @@ FAKE_AUTH_TOKEN = "sk-ant-aut01-fake-auth-token-for-testing-123456789"
|
|||
class TestOptionallyHandleAnthropicOAuth:
|
||||
"""Tests for optionally_handle_anthropic_oauth function."""
|
||||
|
||||
def test_oauth_token_in_authorization_header(self):
|
||||
@pytest.mark.parametrize("header_name", ["authorization", "Authorization", "AUTHORIZATION"])
|
||||
def test_oauth_token_in_authorization_header(self, header_name):
|
||||
"""OAuth token in Authorization header should be detected and headers set correctly."""
|
||||
from litellm.llms.anthropic.common_utils import (
|
||||
optionally_handle_anthropic_oauth,
|
||||
)
|
||||
|
||||
headers = {"authorization": f"Bearer {FAKE_OAUTH_TOKEN}"}
|
||||
headers = {header_name: f"Bearer {FAKE_OAUTH_TOKEN}"}
|
||||
updated_headers, extracted_api_key = optionally_handle_anthropic_oauth(
|
||||
headers, None
|
||||
)
|
||||
|
|
@ -47,6 +48,22 @@ class TestOptionallyHandleAnthropicOAuth:
|
|||
assert updated_headers["anthropic-dangerous-direct-browser-access"] == "true"
|
||||
assert "x-api-key" not in updated_headers
|
||||
|
||||
@pytest.mark.parametrize("api_key_header_name", ["x-api-key", "X-Api-Key"])
|
||||
def test_oauth_removes_x_api_key_any_casing(self, api_key_header_name):
|
||||
"""When OAuth wins, a client x-api-key header is removed whatever its casing."""
|
||||
from litellm.llms.anthropic.common_utils import (
|
||||
optionally_handle_anthropic_oauth,
|
||||
)
|
||||
|
||||
headers = {api_key_header_name: FAKE_REGULAR_KEY, "Authorization": f"Bearer {FAKE_OAUTH_TOKEN}"}
|
||||
updated_headers, extracted_api_key = optionally_handle_anthropic_oauth(
|
||||
headers, None
|
||||
)
|
||||
|
||||
assert extracted_api_key == FAKE_OAUTH_TOKEN
|
||||
assert [name for name in updated_headers if name.lower() == "x-api-key"] == []
|
||||
assert updated_headers["Authorization"] == f"Bearer {FAKE_OAUTH_TOKEN}"
|
||||
|
||||
def test_oauth_token_in_api_key_directly(self):
|
||||
"""OAuth token passed as api_key should set Authorization: Bearer header."""
|
||||
from litellm.llms.anthropic.common_utils import (
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue