feat(auth_v2): define admin team routes in backend/routers on Security DI - #30389
Draft
yassin-berriai wants to merge 8 commits into
Draft
feat(auth_v2): define admin team routes in backend/routers on Security DI#30389yassin-berriai wants to merge 8 commits into
yassin-berriai wants to merge 8 commits into
Conversation
|
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
yassin-berriai
force-pushed
the
litellm_admin_auth_v2
branch
from
June 13, 2026 21:47
a32f6c7 to
4a2c689
Compare
…y DI Move the admin surface toward explicit, backend-owned routers instead of trimming the proxy app by path allowlist. This adds a backend/routers package whose teams router is the source of truth for /admin/teams CRUD plus membership; proxy_server imports and mounts it (guarded by the backend package being importable, since the pip wheel ships only litellm), and backend/main keeps those explicit routes regardless of the allowlist. Every route authenticates through the auth_v2 AuthSecurity stored on app.state.auth_v2 (a require_roles gate over the Principal) rather than the legacy user_api_key_auth dependency; app.state.auth_v2 is wired in the proxy startup once the DB is connected. Two resolver fixes were needed to make the DB-backed path actually work, since it was previously only exercised against an in-memory store: API-key principals now resolve their platform role from the owning user (get_key_object does not join user_role onto the token), and team group writes wrap members_with_roles in prisma Json so upsert_group persists. db_team_to_scim now carries members so team membership round-trips on read.
…ypes Regression tests for upsert_group/get_group/list_groups/delete_group against a fake prisma that mirrors the one behavior they depend on (a Json-wrapped write round-trips as its plain value), so a future drop of the prisma Json wrapper or the typed read fails here rather than only against a live database. Regenerate ui/litellm-dashboard/src/lib/http/schema.d.ts from the proxy OpenAPI spec now that the /admin/teams routes are mounted.
yassin-berriai
force-pushed
the
litellm_admin_auth_v2
branch
from
June 13, 2026 22:02
4a2c689 to
1f6506f
Compare
…tellm_admin_auth_v2 # Conflicts: # backend/main.py # litellm/proxy/auth_v2/resolvers.py # litellm/proxy/proxy_server.py # tests/test_litellm/proxy/auth_v2/test_resolver.py # tests/test_litellm/proxy/test_component_allowlists.py
yassin-berriai
force-pushed
the
litellm_admin_auth_v2
branch
from
July 17, 2026 20:56
d052811 to
fa6a94c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Relevant issues
Stacked on top of #30171 (targets
litellm_fix/auth-module, notmain/litellm_internal_staging).Linear ticket
None
Pre-Submission checklist
make test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewType
🆕 New Feature
Changes
Today the backend component reuses the whole proxy app and trims it down to the admin surface by a path allowlist; the admin routes themselves still live in the proxy and authenticate through the legacy
user_api_key_authdependency. This starts moving that surface toward explicit, backend-owned routers that authenticate through theauth_v2AuthSecuritySecurity layer, with the teams vertical as the first one done end to end.What changed:
backend/routerspackage. Itsteamsrouter is the source of truth for the admin teams surface (POST/GET/PUT/DELETE /admin/teams, list, and membership).proxy_serverimports and mounts it, so the route definitions live inbackend/routersand the proxy includes them rather than owning them. The include is guarded by thebackendpackage being importable, because the pip wheel ships onlylitellmwhile the source tree and Docker image shipbackendtoo; pip-installed proxies simply do not mount the admin routes.request.app.state.auth_v2(arequire_roles(ORG_ADMIN, PLATFORM_ADMIN)gate over the resolvedPrincipal) instead ofuser_api_key_auth.app.state.auth_v2is built in the proxy startup once the DB is connected (anAuthSecurityover theDbIdentityStore).backend/mainkeeps the explicit admin routes regardless of the allowlist; the allowlist still covers the rest of the not-yet-migrated management surface, so nothing is dropped during the migration.Two resolver fixes were needed to make the DB-backed path actually work, since
DbIdentityStore's write path had only ever been exercised against an in-memory store:get_key_objectdoes not joinuser_roleonto the token, so an admin virtual key was coming back role-less and could never pass the role gate.members_with_rolesin prismaJsonsoupsert_grouppersists, anddb_team_to_scimnow carries members so team membership round-trips on read (this also fixes SCIMGET /Groupsreturning empty membership).Scope note: this is deliberately one vertical. The remaining management endpoints are tightly coupled to
UserAPIKeyAuth(budget/limit/permission state thatPrincipalis identity-only by design and does not carry), so they migrate onto this pattern incrementally in follow-ups rather than in a single bulk rewrite.Tests
tests/test_litellm/proxy/test_backend_admin_teams.py: drives the router through a realAuthSecurityand asserts the gate (401 unauthenticated, 401 unknown key, 403 without admin role) and CRUD + membership round-trip.tests/test_litellm/proxy/auth_v2/test_resolver.py: regression that an API key with auser_idbut nouser_roleresolves the role from the user table, plusDbIdentityStoregroup CRUD round-tripping members through prismaJson.tests/test_litellm/proxy/auth_v2/test_utils.py:db_team_to_scimcarries members.tests/test_litellm/proxy/test_component_allowlists.py: updated so the gateway/backend coverage union accounts for the explicit/adminroutes.Screenshots / Proof of Fix
Ran against a live backend (
uvicorn backend.main:appon:4001) backed by a real Postgres. An admin user+key (proxy_admin) and a reader user+key (internal_user) were created via/user/new, then:A team created via
/admin/teamsis a real DB team visible to the legacy endpoint (shared store):And the admin routes show up on the proxy app's OpenAPI (source of truth):