diff --git a/src/authentication/noop.py b/src/authentication/noop.py index 8d0e9bd84..259dd1168 100644 --- a/src/authentication/noop.py +++ b/src/authentication/noop.py @@ -1,6 +1,6 @@ """Manage authentication flow for FastAPI endpoints with no-op auth.""" -from fastapi import Request +from fastapi import HTTPException, Request from constants import ( DEFAULT_USER_NAME, @@ -50,5 +50,7 @@ async def __call__(self, request: Request) -> tuple[str, str, bool, str]: ) # try to extract user ID from request user_id = request.query_params.get("user_id", DEFAULT_USER_UID) + if not user_id: + raise HTTPException(status_code=400, detail="user_id cannot be empty") logger.debug("Retrieved user ID: %s", user_id) return user_id, DEFAULT_USER_NAME, self.skip_userid_check, NO_USER_TOKEN diff --git a/src/authentication/noop_with_token.py b/src/authentication/noop_with_token.py index 3d1b0ed98..6d7777044 100644 --- a/src/authentication/noop_with_token.py +++ b/src/authentication/noop_with_token.py @@ -9,7 +9,7 @@ - Returns a tuple: (user_id, DEFAULT_USER_NAME, user_token). """ -from fastapi import Request +from fastapi import HTTPException, Request from constants import ( DEFAULT_USER_NAME, @@ -63,5 +63,7 @@ async def __call__(self, request: Request) -> tuple[str, str, bool, str]: user_token = extract_user_token(request.headers) # try to extract user ID from request user_id = request.query_params.get("user_id", DEFAULT_USER_UID) + if not user_id: + raise HTTPException(status_code=400, detail="user_id cannot be empty") logger.debug("Retrieved user ID: %s", user_id) return user_id, DEFAULT_USER_NAME, self.skip_userid_check, user_token diff --git a/tests/e2e/features/authorized_noop.feature b/tests/e2e/features/authorized_noop.feature index 62edb9bf9..7da0ef959 100644 --- a/tests/e2e/features/authorized_noop.feature +++ b/tests/e2e/features/authorized_noop.feature @@ -35,14 +35,14 @@ Feature: Authorized endpoint API tests for the noop authentication module {"user_id": "00000000-0000-0000-0000-000","username": "lightspeed-user","skip_userid_check": true} """ - Scenario: Check if the authorized endpoint works when providing empty user_id + Scenario: Check if the authorized endpoint rejects empty user_id Given The system is in default state And I set the Authorization header to Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva When I access endpoint "authorized" using HTTP POST method with user_id "" - Then The status code of the response is 200 + Then The status code of the response is 400 And The body of the response is the following """ - {"user_id": "","username": "lightspeed-user","skip_userid_check": true} + {"detail": "user_id cannot be empty"} """ Scenario: Check if the authorized endpoint works when providing proper user_id diff --git a/tests/e2e/features/authorized_noop_token.feature b/tests/e2e/features/authorized_noop_token.feature index b654a77d2..f977790f5 100644 --- a/tests/e2e/features/authorized_noop_token.feature +++ b/tests/e2e/features/authorized_noop_token.feature @@ -32,14 +32,14 @@ Feature: Authorized endpoint API tests for the noop-with-token authentication mo {"user_id": "00000000-0000-0000-0000-000","username": "lightspeed-user","skip_userid_check": true} """ - Scenario: Check if the authorized endpoint works when providing empty user_id + Scenario: Check if the authorized endpoint rejects empty user_id Given The system is in default state And I set the Authorization header to Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva When I access endpoint "authorized" using HTTP POST method with user_id "" - Then The status code of the response is 200 + Then The status code of the response is 400 And The body of the response is the following """ - {"user_id": "","username": "lightspeed-user","skip_userid_check": true} + {"detail": "user_id cannot be empty"} """ Scenario: Check if the authorized endpoint works when providing proper user_id diff --git a/tests/unit/authentication/test_noop.py b/tests/unit/authentication/test_noop.py index e651ff673..d179f33e7 100644 --- a/tests/unit/authentication/test_noop.py +++ b/tests/unit/authentication/test_noop.py @@ -1,6 +1,8 @@ """Unit tests for functions defined in authentication/noop.py""" -from fastapi import Request +from fastapi import Request, HTTPException +import pytest + from authentication.noop import NoopAuthDependency from constants import DEFAULT_USER_NAME, DEFAULT_USER_UID, NO_USER_TOKEN @@ -37,3 +39,18 @@ async def test_noop_auth_dependency_custom_user_id() -> None: assert username == DEFAULT_USER_NAME assert skip_userid_check is True assert user_token == NO_USER_TOKEN + + +async def test_noop_auth_dependency_empty_user_id() -> None: + """Test that NoopAuthDependency rejects empty user_id with HTTP 400.""" + dependency = NoopAuthDependency() + + # Create a mock request with empty user_id + request = Request(scope={"type": "http", "query_string": b"user_id="}) + + # Assert that an HTTPException is raised for empty user_id + with pytest.raises(HTTPException) as exc_info: + await dependency(request) + + assert exc_info.value.status_code == 400 + assert exc_info.value.detail == "user_id cannot be empty" diff --git a/tests/unit/authentication/test_noop_with_token.py b/tests/unit/authentication/test_noop_with_token.py index 9d08a87a3..d120f072b 100644 --- a/tests/unit/authentication/test_noop_with_token.py +++ b/tests/unit/authentication/test_noop_with_token.py @@ -117,3 +117,26 @@ async def test_noop_with_token_auth_dependency_no_bearer() -> None: detail = cast(dict[str, str], exc_info.value.detail) assert detail["response"] == ("Missing or invalid credentials provided by client") assert detail["cause"] == "No token found in Authorization header" + + +async def test_noop_with_token_auth_dependency_empty_user_id() -> None: + """Test that NoopWithTokenAuthDependency rejects empty user_id with HTTP 400.""" + dependency = NoopWithTokenAuthDependency() + + # Create a mock request with empty user_id but valid token + request = Request( + scope={ + "type": "http", + "query_string": b"user_id=", + "headers": [ + (b"authorization", b"Bearer spongebob-token"), + ], + }, + ) + + # Assert that an HTTPException is raised for empty user_id + with pytest.raises(HTTPException) as exc_info: + await dependency(request) + + assert exc_info.value.status_code == 400 + assert exc_info.value.detail == "user_id cannot be empty"