Merge pull request #2680 from langbot-app/fix/auth-invalid-json-contract-20261017

fix(auth): reject malformed credential payloads before authentication
This commit is contained in:
huanghuoguoguo
2026-10-17 20:11:01 +08:00
committed by GitHub
2 changed files with 36 additions and 23 deletions
+31 -22
View File
@@ -231,33 +231,42 @@ class TestInvalidPayload:
"""Tests for error handling with invalid payloads."""
@pytest.mark.asyncio
async def test_missing_json_body(self, quart_test_client):
"""
POST endpoint without JSON body handles gracefully.
"""
# /api/v1/user/auth expects JSON with 'user' and 'password'
async def test_missing_json_body(self, quart_test_client, fake_api_app):
"""A missing login body is rejected before authentication."""
response = await quart_test_client.post('/api/v1/user/auth')
# Should return error (500, 400, or 401) with stable JSON structure
assert response.status_code in (400, 500, 401)
data = await response.get_json()
# Verify error response has expected structure
assert 'code' in data
assert 'msg' in data
assert response.status_code == 400
assert await response.get_json() == {'code': -1, 'msg': 'Invalid request parameters'}
fake_api_app.user_service.authenticate.assert_not_awaited()
@pytest.mark.asyncio
async def test_invalid_json_structure(self, quart_test_client):
"""
POST with wrong JSON structure returns stable error.
"""
response = await quart_test_client.post('/api/v1/user/auth', json={'wrong_field': 'value'})
@pytest.mark.parametrize(
'payload',
[
{'wrong_field': 'value'},
[],
{'user': None, 'password': 'secret'},
{'user': '[email protected]', 'password': 42},
],
)
async def test_invalid_json_structure(self, quart_test_client, fake_api_app, payload):
"""Malformed credential fields never reach the authentication service."""
response = await quart_test_client.post('/api/v1/user/auth', json=payload)
# Should return error with stable JSON structure
assert response.status_code in (400, 500, 401)
data = await response.get_json()
assert 'code' in data
assert 'msg' in data
assert response.status_code == 400
assert await response.get_json() == {'code': -1, 'msg': 'Invalid request parameters'}
fake_api_app.user_service.authenticate.assert_not_awaited()
@pytest.mark.asyncio
@pytest.mark.parametrize('password', ['', 'existing-password'])
async def test_string_credentials_reach_authentication(self, quart_test_client, fake_api_app, password):
response = await quart_test_client.post(
'/api/v1/user/auth', json={'user': '[email protected]', 'password': password}
)
assert response.status_code == 200
assert (await response.get_json())['data']['token'] == 'fake_token'
fake_api_app.user_service.authenticate.assert_awaited_once_with('[email protected]', password, None)
@pytest.mark.usefixtures('mock_circular_import_chain')