From 4ddbb91825f47dfcb1116e518fc22731a74c1d6b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 21 May 2026 18:47:51 +0000 Subject: [PATCH] fix(jwt): include issuer-normalized team id in get_all_jwt_team_ids The aggregator for team IDs only consulted the issuer-normalized claim for the plural (team_ids) path and fell back to the global config for the singular path. When an operator configures team_id_jwt_field only at the issuer level, get_team_id correctly returned the mapped value but get_all_jwt_team_ids silently dropped it, causing membership reconciliation to disagree with request routing. Co-authored-by: Yassin Kortam --- litellm/proxy/auth/handle_jwt.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/litellm/proxy/auth/handle_jwt.py b/litellm/proxy/auth/handle_jwt.py index 4b2bebbd036..314903825ba 100644 --- a/litellm/proxy/auth/handle_jwt.py +++ b/litellm/proxy/auth/handle_jwt.py @@ -284,12 +284,18 @@ class JWTHandler: default-team behavior should still go through ``get_team_id``. """ team_ids: List[str] = list(self.get_team_ids_from_jwt(token)) - if self.litellm_jwtauth.team_id_jwt_field is not None: + singular: Any = None + if self._has_trusted_issuer_normalized_claim( + token=token, claim=self.LITELLM_TEAM_ID_CLAIM + ): + singular = token.get(self.LITELLM_TEAM_ID_CLAIM) + elif self.litellm_jwtauth.team_id_jwt_field is not None: singular = get_nested_value( data=token, key_path=self.litellm_jwtauth.team_id_jwt_field, default=None, ) + if singular is not None: if isinstance(singular, list): for item in singular: if item is None: