fix: replace user api key auth with authorization or cookie for mcp server creation - #27190
Conversation
| master_key, | ||
| algorithms=["HS256"], | ||
| # UI session cookies may omit exp; don't require it. | ||
| options={"verify_exp": False}, |
There was a problem hiding this comment.
High: Expired session cookie accepted
verify_exp is disabled when turning the UI token cookie into an API key for the MCP OAuth endpoints. An attacker who obtained an old UI cookie can keep using it to authorize or exchange MCP OAuth tokens after the session expiration that protects normal cookie/JWT validation has passed; decode the cookie with expiration verification enabled and only exempt tokens that truly have no exp claim if that legacy path is required.
MCP OAuth endpoint auth fallback reviewedThis PR changes the MCP OAuth authorize/token endpoints to authenticate with an Authorization header or, for browser navigation, a signed UI token cookie that is converted back into the contained API key before normal API-key validation and per-server access checks. I reviewed the changed helper, endpoint dependencies, surrounding server lookup authorization, and UI cookie issuance paths; no new security issue was found in the diff. Status: 1 open |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Greptile SummaryThis PR fixes a 401 error on MCP OAuth browser-navigation endpoints (
Confidence Score: 5/5The core logic change is narrow and self-contained; per-server access control is fully preserved and the new dependency routes all auth through the existing The cookie-decode path mirrors an established pattern already present in the codebase. The fallback is guarded by both litellm/proxy/management_endpoints/mcp_management_endpoints.py — the unresolved items in prior review threads (exp verification, byok_session guard) are worth resolving before this merges.
|
| Filename | Overview |
|---|---|
| litellm/proxy/management_endpoints/mcp_management_endpoints.py | Adds _mcp_oauth_user_api_key_auth dependency with cookie fallback for browser OAuth flows; two previously flagged security concerns (exp verification, byok_session guard) remain open in prior review threads. |
| tests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py | Adds two properly mocked async tests covering cookie-fallback and Authorization-header-priority paths; no real network calls. |
Reviews (2): Last reviewed commit: "updated tests" | Re-trigger Greptile
| algorithms=["HS256"], | ||
| # UI session cookies may omit exp; don't require it. | ||
| options={"verify_exp": False}, | ||
| ) |
There was a problem hiding this comment.
verify_exp: False deviates from the reference security pattern
byok_oauth_endpoints.py:108-115 decodes the same cookie with options={"require": ["exp"]}, explicitly bounding a leaked session cookie's lifetime. This PR flips to verify_exp: False, accepting any master_key-signed JWT even if it carries an exp claim that has already passed. The comment acknowledges UI tokens currently omit exp (confirmed by ReturnedUITokenObject), but disabling expiry verification entirely means a cookie whose JWT was intentionally crafted with a past exp would still decode successfully — security then depends entirely on _user_api_key_auth_builder rejecting the embedded API key via DB lookup. Consider either adding exp to ReturnedUITokenObject and keeping exp-verification on, or at minimum using options={} (the default) so that when exp is present it is still checked.
| # UI session cookies may omit exp; don't require it. | ||
| options={"verify_exp": False}, | ||
| ) | ||
| if decoded.get("login_method") in ("sso", "username_password"): |
There was a problem hiding this comment.
Missing explicit
byok_session token guard
byok_oauth_endpoints.py:119-120 explicitly checks if payload.get("type") == "byok_session": return None before inspecting login_method, with an in-code comment explaining that byok_session JWTs must never be replayable as UI cookies. The new function omits that check and relies implicitly on login_method being absent from byok_session tokens. While that currently blocks them, adding the explicit type guard would make the defence-in-depth explicit and resistant to future byok_session token schema changes.
|
duplicate of #27106 |
73de892
into
BerriAI:litellm_internal_staging
…erver creation (BerriAI#27190) * fix: replace user api key auth with authorization or cookie for mcp server creation * updated tests
…erver creation (BerriAI#27190) * fix: replace user api key auth with authorization or cookie for mcp server creation * updated tests
Relevant issues
Linear ticket
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
tests/test_litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewDelays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
CI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Screenshots / Proof of Fix
Type
🐛 Bug Fix
Changes
Root cause: Commit 9deefc0 added dependencies=[Depends(user_api_key_auth)] to
/v1/mcp/server/oauth/{server_id}/authorize and /v1/mcp/server/oauth/{server_id}/token. Both endpoints are reached via browser-based OAuth flows (/authorizevia window.location.href redirect,/tokenviafetch()) neither of which sends an Authorization header. With master_key set, the standard auth raises 401.Fix: Added a new _mcp_oauth_user_api_key_auth dependency in litellm/proxy/management_endpoints/mcp_management_endpoints.py that:
This mirrors the existing cookie-decode pattern in byok_oauth_endpoints.py:104-124. The per-server access control added by 9deefc0 is fully preserved — non-admins are still blocked from temp-cache servers.
Files changed:
litellm/proxy/management_endpoints/mcp_management_endpoints.py- new_mcp_oauth_user_api_key_auth dependency;/authorizeand/tokenswitch to using ittests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py- two new tests:cookie-fallbackpath andAuthorization-header-prioritypath