litellm/tests/test_litellm/proxy/auth
milan-berri a7ecf6b5b1
feat(jwt-auth): opt-in fallback to DB team on unresolved JWT claim (#28913)
* fix(jwt-auth): defer to single-team DB fallback on claim mismatch

Extends the single-team DB fallback introduced in #26418 to two more
cases where it previously could not run:

* `find_and_validate_specific_team_id`: when `team_id_jwt_field` is
  configured and a claim value is present in the token but the team
  does not exist in the LiteLLM DB (HTTPException 404 from
  `get_team_object`), return `(None, None)` instead of raising — the
  auth_builder fallback then attributes the request to the user's
  single DB team. Only HTTPException is caught; other errors (e.g.
  "No DB Connected") still propagate.

* `find_team_with_model_access`: when none of the `team_ids_jwt_field`
  groups resolve to a real LiteLLM team, return `(None, None)` instead
  of raising 403 so the same fallback path runs. If at least one group
  DID resolve to a team but none granted the requested model, the
  original 403 is preserved (legitimate access denial — not a claim
  mismatch). Tracked via the new `any_claim_team_resolved` flag.

The strict `is_required_team_id` raise and `enforce_team_based_model_access`
raise remain unchanged. Unit tests cover both new soft-fail paths and
guard each preserved path (strict required, enforce_team_based, the
preserved 403, and the non-HTTPException propagation).

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(jwt-auth): narrow HTTPException catch to 404 (greptile review)

Address Greptile review comments on #28913:

* `find_and_validate_specific_team_id`: re-raise HTTPException when
  `status_code != 404`, pinning the catch to the "team doesn't exist
  in db" path documented for `get_team_object`. A future change that
  introduces a different status code (e.g. 403 for a blocked team)
  will now propagate instead of silently falling through to the
  single-team DB fallback.

* Add `test_find_and_validate_specific_team_id_non_404_http_exception_propagates`
  parametrised over 400 / 403 / 500 to lock in the contract.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(jwt-auth): gate claim-mismatch fallback behind opt-in flag

The unresolved-team-claim fallback added in the previous commit
weakened the strict claim-based authorization contract by default —
an authenticated user whose JWT carries a stale or invalid team
claim could still consume their single DB team's models/quota via
the fallback.

Gate both soft-fail paths in `find_and_validate_specific_team_id`
and `find_team_with_model_access` behind a new opt-in flag
`team_claim_fallback` on `LiteLLM_JWTAuth` (default False).

Default-off preserves the pre-existing strict behavior. Operators
who intentionally treat IdP team claims as advisory (e.g. machine
tokens whose group claims live in a separate namespace from
LiteLLM team_ids) opt in via config.

Adds two regression tests guarding the default-off behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 01:09:03 +03:00
..
test_admin_viewer_handler_access.py fix(rbac): restore admin-viewer read parity for Logs page + settings reads 2026-04-29 19:21:41 -07:00
test_auth_checks.py fix(auth): expand all-team-models sentinel in can_key_call_model for batch validation (#29746) 2026-06-05 09:04:45 -07:00
test_auth_exception_handler.py fix: 400 on Anthropic context overflow; seed identity on failed auth (#29848) 2026-06-06 14:57:41 -07:00
test_auth_hot_path_network_requests.py fix: update docker test file to right path 2026-02-19 18:44:28 +05:30
test_auth_utils.py fix(proxy): resolve managed video model ids for auth (#29545) 2026-06-02 19:31:36 -07:00
test_banned_params_extra_body.py chore(tests): drop redundant membership check; trim test comment 2026-05-14 03:39:15 +00:00
test_cli_auth.py cover cli sso start validation 2026-04-29 17:25:32 -07:00
test_custom_auth_end_user_budget.py Litellm oss staging 030626 (#29578) 2026-06-03 11:01:51 -07:00
test_handle_jwt.py feat(jwt-auth): opt-in fallback to DB team on unresolved JWT claim (#28913) 2026-06-09 01:09:03 +03:00
test_info_routes.py style: run black formatter on files from main merge 2026-04-17 13:02:59 -07:00
test_litellm_license.py style: run black formatter on files from main merge 2026-04-17 13:02:59 -07:00
test_login_utils.py style: run black formatter on files from main merge 2026-04-17 13:02:59 -07:00
test_mcp_ip_filtering.py [internal copy of #28008] Support MCP OAuth passthrough and issuer-scoped JWT auth (#28356) 2026-06-02 12:22:04 -07:00
test_model_checks.py fix(proxy): hydrate wildcard discovery credentials (#28284) (#28419) 2026-05-20 20:03:05 -07:00
test_model_checks_fallbacks.py style: run black formatter on files from main merge 2026-04-17 13:02:59 -07:00
test_multi_budget_windows.py feat: multiple concurrent budget windows per API key and team (#24883) (#25109) 2026-04-06 14:02:04 -07:00
test_oauth2_proxy_hook.py chore(auth): require trusted proxy for header identity auth 2026-04-29 21:20:21 -07:00
test_object_permission_loading.py style: run black formatter on files from main merge 2026-04-17 13:02:59 -07:00
test_onboarding.py chore(auth): address onboarding review follow-ups 2026-04-29 19:10:30 -07:00
test_organization_budget_enforcement.py style: run black formatter on files from main merge 2026-04-17 13:02:59 -07:00
test_password_hashing.py chore: fixes 2026-03-30 18:36:58 -07:00
test_route_checks.py fix(proxy): passthrough 404 when SERVER_ROOT_PATH is set (#29658) 2026-06-04 07:44:51 -07:00
test_router_override_fallback_auth.py [Fix] Proxy: Repair Merge Fallout In Router-Override Fallback Auth 2026-05-01 17:48:51 -07:00
test_team_member_budget.py Fix team member budget enforcement without user row (#27273) 2026-05-06 11:42:29 -07:00
test_unmapped_model_budget_enforcement.py perf: eliminate per-request callback scanning on proxy hot path (#27858) 2026-05-14 09:28:31 -07:00
test_user_api_key_auth.py Litellm oss staging 080626 (#29932) 2026-06-08 13:49:52 -07:00