diff --git a/litellm/proxy/auth/auth_utils.py b/litellm/proxy/auth/auth_utils.py index 3261d158899e..490bb06da025 100644 --- a/litellm/proxy/auth/auth_utils.py +++ b/litellm/proxy/auth/auth_utils.py @@ -481,10 +481,22 @@ def get_end_user_id_from_request_body( # and to ensure it's fetched at runtime. from litellm.proxy.proxy_server import general_settings + # Config gate: If `general_settings.user_header_target == "internal_user"`, + # we should NOT use the forwarded header to populate End User. + # This ensures we don't duplicate the value into both Internal and End User fields. + _map_to_internal_user = False + try: + _map_to_internal_user = ( + isinstance(general_settings.get("user_header_target"), str) + and general_settings.get("user_header_target", "").lower() + == "internal_user" + ) + except Exception: + _map_to_internal_user = False + # Check 1: Custom Header from general_settings.user_header_name (only if request_headers is provided) - # User query: "system not respecting user_header_name property" - # This implies the key in general_settings is 'user_header_name'. - if request_headers is not None: + # Skip using header as End User when mapping-to-internal-user is enabled by config. + if request_headers is not None and _map_to_internal_user is not True: user_id_header_config_key = "user_header_name" custom_header_name_to_check = general_settings.get(user_id_header_config_key) diff --git a/litellm/proxy/litellm_pre_call_utils.py b/litellm/proxy/litellm_pre_call_utils.py index 95f1eccffe46..5888cfc7c336 100644 --- a/litellm/proxy/litellm_pre_call_utils.py +++ b/litellm/proxy/litellm_pre_call_utils.py @@ -729,8 +729,27 @@ async def add_litellm_data_to_request( # noqa: PLR0915 # Parse user info from headers user = LiteLLMProxyRequestSetup.get_user_from_headers(_headers, general_settings) if user is not None: - if user_api_key_dict.end_user_id is None: - user_api_key_dict.end_user_id = user + # Config gate: If `general_settings.user_header_target == "internal_user"`, + # map the forwarded user header to Internal User (user_id) instead of End User (end_user_id). + # Default behavior (no config) keeps mapping to End User + _map_to_internal_user = False + if general_settings is not None: + try: + _map_to_internal_user = ( + isinstance(general_settings.get("user_header_target"), str) + and general_settings.get("user_header_target", "").lower() + == "internal_user" + ) + except Exception: + _map_to_internal_user = False + + if _map_to_internal_user is True: + # Set Internal User + user_api_key_dict.user_id = user + else: + # Default behavior: set End User + if user_api_key_dict.end_user_id is None: + user_api_key_dict.end_user_id = user if "user" not in data: data["user"] = user