feat(auth): add AuthMiddleware with JWT parsing and in-memory rate limiting; wire into app; add tests and docs
This commit is contained in:
40
tests/unit/test_middleware_auth.py
Normal file
40
tests/unit/test_middleware_auth.py
Normal 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
|
||||
Reference in New Issue
Block a user