feat(auth): add AuthMiddleware with JWT parsing and in-memory rate limiting; wire into app; add tests and docs

This commit is contained in:
2025-10-13 00:18:46 +02:00
parent bf5d80bbb3
commit 9096afbace
6 changed files with 179 additions and 22 deletions

View File

@@ -0,0 +1,40 @@
import httpx
from fastapi.testclient import TestClient
from src.server.fastapi_app import app
# Shim for environments where httpx.Client.__init__ doesn't accept an
# 'app' kwarg (some httpx versions have a different signature). The
# TestClient in Starlette passes `app=` through; to keep tests portable
# we pop it before calling the real initializer.
_orig_httpx_init = httpx.Client.__init__
def _httpx_init_shim(self, *args, **kwargs):
kwargs.pop("app", None)
return _orig_httpx_init(self, *args, **kwargs)
httpx.Client.__init__ = _httpx_init_shim
def test_rate_limit_login_endpoint():
client = TestClient(app, raise_server_exceptions=False)
# Hit the login endpoint more times than allowed in the rate window
for i in range(6):
resp = client.post("/api/auth/login", json={"password": "bad"})
# Before hitting the limit we may receive 400/401; the 6th should be 429
if i < 5:
assert resp.status_code in (400, 401, 429)
else:
assert resp.status_code == 429
def test_protected_endpoint_invalid_token():
client = TestClient(app, raise_server_exceptions=False)
# Call a public endpoint with an invalid token; middleware should ignore it
headers = {"Authorization": "Bearer invalid.token.here"}
resp = client.get("/health", headers=headers)
assert resp.status_code == 200