diff --git a/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py b/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py index 5992d3e86de..34c7fe783a1 100644 --- a/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py +++ b/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py @@ -7,6 +7,7 @@ from starlette.requests import Request from starlette.types import Scope from litellm._logging import verbose_logger +from litellm.constants import DEFAULT_MANAGEMENT_OBJECT_IN_MEMORY_CACHE_TTL from litellm.proxy._types import ( LiteLLM_TeamTable, ProxyException, @@ -1155,6 +1156,7 @@ class MCPRequestHandler: await user_api_key_cache.async_set_cache( key=cache_key, value=MCPRequestHandler._ORG_NO_PERMISSION_SENTINEL, + ttl=DEFAULT_MANAGEMENT_OBJECT_IN_MEMORY_CACHE_TTL, ) return None @@ -1164,7 +1166,9 @@ class MCPRequestHandler: # get_end_user_object / get_team_object in auth_checks.py). obj_perm = LiteLLM_ObjectPermissionTable(**org_row.object_permission.dict()) await user_api_key_cache.async_set_cache( - key=cache_key, value=obj_perm.dict() + key=cache_key, + value=obj_perm.dict(), + ttl=DEFAULT_MANAGEMENT_OBJECT_IN_MEMORY_CACHE_TTL, ) return obj_perm except Exception as e: @@ -1334,6 +1338,7 @@ class MCPRequestHandler: await user_api_key_cache.async_set_cache( key=cache_key, value=MCPRequestHandler._AGENT_NO_PERMISSION_SENTINEL, + ttl=DEFAULT_MANAGEMENT_OBJECT_IN_MEMORY_CACHE_TTL, ) return None @@ -1341,7 +1346,9 @@ class MCPRequestHandler: **agent_row.object_permission.dict() ) await user_api_key_cache.async_set_cache( - key=cache_key, value=obj_perm.dict() + key=cache_key, + value=obj_perm.dict(), + ttl=DEFAULT_MANAGEMENT_OBJECT_IN_MEMORY_CACHE_TTL, ) return obj_perm except Exception as e: diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index 23e786a690e..290324d94b5 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -4397,8 +4397,11 @@ class JWTIssuerConfig(BaseModel): """ Issuer-bound JWT validation configuration. - When configured, LiteLLM selects this issuer by the token's unverified `iss` - claim, then validates the token only against this issuer's JWKS and audience. + When a token's unverified `iss` claim matches an entry in + ``LiteLLM_JWTAuth.issuers``, LiteLLM validates it only against that + issuer's JWKS and audience. Tokens whose `iss` does not match any + configured issuer fall back to the global JWT_AUDIENCE/JWT_ISSUER + validation path; `issuers` is additive routing, not an allow-list. """ issuer: str = Field(description="Exact expected JWT issuer (`iss`) value.") @@ -4550,7 +4553,7 @@ class LiteLLM_JWTAuth(LiteLLMPydanticObjectBase): ) issuers: Optional[List[JWTIssuerConfig]] = Field( default=None, - description="Optional issuer-bound JWT validation rules. When set, tokens must match one configured issuer by exact `iss` claim before JWKS lookup.", + description="Optional issuer-bound JWT validation rules. When a token's `iss` matches a configured issuer, validation uses that issuer's JWKS, audience, and claim mappings. Tokens with an unlisted `iss` fall back to the global JWT_AUDIENCE/JWT_ISSUER validation path — this is additive routing, not an allow-list.", ) #########################################################