diff --git a/litellm/proxy/auth/handle_jwt.py b/litellm/proxy/auth/handle_jwt.py index bfad9f0c3c7..48bbd8e2150 100644 --- a/litellm/proxy/auth/handle_jwt.py +++ b/litellm/proxy/auth/handle_jwt.py @@ -89,7 +89,9 @@ class JWTHandler: self.leeway = leeway @staticmethod - def is_jwt(token: str): + def is_jwt(token: Optional[str]) -> bool: + if token is None: + return False parts = token.split(".") return len(parts) == 3 diff --git a/tests/proxy_unit_tests/test_jwt.py b/tests/proxy_unit_tests/test_jwt.py index 24cf15a3214..a5be1a3a42d 100644 --- a/tests/proxy_unit_tests/test_jwt.py +++ b/tests/proxy_unit_tests/test_jwt.py @@ -1331,6 +1331,9 @@ def test_jwt_handler_is_jwt_static_method(): # Test with empty string assert JWTHandler.is_jwt("") == False + # Test with None (missing Authorization header) + assert JWTHandler.is_jwt(None) == False + @pytest.mark.parametrize( "requested_model, should_work", diff --git a/tests/test_litellm/proxy/auth/test_user_api_key_auth.py b/tests/test_litellm/proxy/auth/test_user_api_key_auth.py index 81ca758983b..6e000f9c0e3 100644 --- a/tests/test_litellm/proxy/auth/test_user_api_key_auth.py +++ b/tests/test_litellm/proxy/auth/test_user_api_key_auth.py @@ -567,6 +567,10 @@ class TestJWTOAuth2Coexistence: assert JWTHandler.is_jwt("Bearer token") is False assert JWTHandler.is_jwt("two.parts") is False + def test_is_jwt_returns_false_for_none(self): + """None token (missing Authorization header) should not be treated as JWT.""" + assert JWTHandler.is_jwt(None) is False + @pytest.mark.asyncio async def test_both_enabled_opaque_token_uses_oauth2(self): """