mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-05 02:41:56 +00:00
fix(tests): align merged JWT and MCP cold-start assertions
Update the tests carried over from PR #28008 to match the assertions on the staging branch: - tests/test_litellm/proxy/auth/test_handle_jwt.py: unknown issuers now fall back to the legacy JWT_PUBLIC_KEY_URL path (per litellm_feat/v1.84.0-mcp-gateway-jwt-auth's '\''fall back to global JWKS on unknown issuer'\''), and mapped issuer claims that are absent no longer fail closed — they simply leave the normalised LiteLLM internal claim absent. - tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py: the aggregate '\''/mcp'\'' route still triggers the delegate-auth-to-upstream lookup once for the header-supplied server name; cold-start admission must NOT fire on top of that. Tighten the assertion to assert_called_once_with so a future regression that re-enters cold-start is caught. Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
This commit is contained in:
parent
6697fdb03d
commit
418e266968
2 changed files with 30 additions and 21 deletions
|
|
@ -918,12 +918,13 @@ class TestMCPPassthroughColdStartAdmission:
|
|||
await MCPRequestHandler.process_mcp_request(scope)
|
||||
|
||||
assert exc_info.value.status_code == 401
|
||||
# Cold-start lookup (signaled by the ``client_ip`` kwarg) must not
|
||||
# fire for the aggregate ``/mcp`` route — only path-targeted
|
||||
# routes are eligible for OAuth discovery admission.
|
||||
assert not any(
|
||||
"client_ip" in c.kwargs
|
||||
for c in mock_mgr.get_mcp_server_by_name.call_args_list
|
||||
# The delegate-auth-to-upstream check looks up the header-supplied
|
||||
# server name once. Cold-start admission must NOT then fire for
|
||||
# the aggregate ``/mcp`` route — only path-targeted routes are
|
||||
# eligible for OAuth discovery admission — so the lookup must
|
||||
# be called exactly once (by the delegate check).
|
||||
mock_mgr.get_mcp_server_by_name.assert_called_once_with(
|
||||
"passthrough_server", client_ip=""
|
||||
)
|
||||
|
||||
async def test_cold_start_rejects_server_specific_authorization_header(self):
|
||||
|
|
|
|||
|
|
@ -2871,16 +2871,12 @@ async def test_get_public_key_tries_next_jwks_url_when_kid_missing(monkeypatch):
|
|||
|
||||
first_jwks_url = "https://first.example.com/keys"
|
||||
second_jwks_url = "https://second.example.com/keys"
|
||||
monkeypatch.setenv(
|
||||
"JWT_PUBLIC_KEY_URL", f"{first_jwks_url}, {second_jwks_url},,"
|
||||
)
|
||||
monkeypatch.setenv("JWT_PUBLIC_KEY_URL", f"{first_jwks_url}, {second_jwks_url},,")
|
||||
_, first_jwk = _get_rsa_key_and_jwk(kid="first-key")
|
||||
_, second_jwk = _get_rsa_key_and_jwk(kid="second-key")
|
||||
cache = DualCache()
|
||||
cache.set_cache(key=f"litellm_jwt_auth_keys_{first_jwks_url}", value=[first_jwk])
|
||||
cache.set_cache(
|
||||
key=f"litellm_jwt_auth_keys_{second_jwks_url}", value=[second_jwk]
|
||||
)
|
||||
cache.set_cache(key=f"litellm_jwt_auth_keys_{second_jwks_url}", value=[second_jwk])
|
||||
jwt_handler = JWTHandler()
|
||||
jwt_handler.update_environment(
|
||||
prisma_client=None,
|
||||
|
|
@ -2902,8 +2898,7 @@ def test_get_jwks_url_for_issuer_falls_back_to_discovery_document():
|
|||
jwks_url = jwt_handler._get_jwks_url_for_issuer(issuer_config=issuer_config)
|
||||
|
||||
assert (
|
||||
jwks_url
|
||||
== "https://issuer.example.com/tenant/.well-known/openid-configuration"
|
||||
jwks_url == "https://issuer.example.com/tenant/.well-known/openid-configuration"
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -3002,7 +2997,13 @@ async def test_multi_issuer_jwt_maps_kubernetes_namespace_claim(monkeypatch):
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_multi_issuer_jwt_rejects_unknown_issuer(monkeypatch):
|
||||
async def test_multi_issuer_jwt_unknown_issuer_falls_back_to_global_jwks(monkeypatch):
|
||||
"""Tokens whose ``iss`` is not in the configured issuers list fall through
|
||||
to the legacy ``JWT_PUBLIC_KEY_URL`` path so operators can add the new
|
||||
``issuers`` list to a live deployment without breaking existing tokens
|
||||
minted by non-configured IdPs. With no global JWKS configured, the legacy
|
||||
path surfaces a ``Missing JWT Public Key URL from environment.`` error.
|
||||
"""
|
||||
monkeypatch.delenv("JWT_AUDIENCE", raising=False)
|
||||
monkeypatch.delenv("JWT_PUBLIC_KEY_URL", raising=False)
|
||||
|
||||
|
|
@ -3028,7 +3029,7 @@ async def test_multi_issuer_jwt_rejects_unknown_issuer(monkeypatch):
|
|||
with pytest.raises(Exception) as exc:
|
||||
await jwt_handler.auth_jwt(token=token)
|
||||
|
||||
assert "Unsupported JWT issuer" in str(exc.value)
|
||||
assert "Missing JWT Public Key URL from environment." in str(exc.value)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
@ -3106,7 +3107,15 @@ async def test_multi_issuer_jwt_same_kid_does_not_cross_issuer_keys(monkeypatch)
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_multi_issuer_jwt_missing_mapped_claim_fails_closed(monkeypatch):
|
||||
async def test_multi_issuer_jwt_missing_mapped_claim_leaves_user_id_unset(
|
||||
monkeypatch,
|
||||
):
|
||||
"""Mapped issuer claims behave like the global ``litellm_jwtauth`` path —
|
||||
present claims override the normalised value, missing ones simply leave
|
||||
the corresponding LiteLLM-internal claim absent (rather than failing the
|
||||
JWT outright). This keeps multi-issuer auth tolerant of tokens that omit
|
||||
optional fields like email or org id.
|
||||
"""
|
||||
monkeypatch.delenv("JWT_AUDIENCE", raising=False)
|
||||
monkeypatch.delenv("JWT_PUBLIC_KEY_URL", raising=False)
|
||||
|
||||
|
|
@ -3131,11 +3140,10 @@ async def test_multi_issuer_jwt_missing_mapped_claim_fails_closed(monkeypatch):
|
|||
kid="issuer-key",
|
||||
)
|
||||
|
||||
with pytest.raises(Exception) as exc:
|
||||
await jwt_handler.auth_jwt(token=token)
|
||||
claims = await jwt_handler.auth_jwt(token=token)
|
||||
|
||||
assert "missing required mapped claim: email" in str(exc.value)
|
||||
assert "Validation fails" not in str(exc.value)
|
||||
assert claims[jwt_handler.LITELLM_JWT_ISSUER_CLAIM] == issuer
|
||||
assert jwt_handler.LITELLM_USER_ID_CLAIM not in claims
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue