feat: add rate limiting middleware for authentication endpoints
Add slowapi-based rate limiting: 5/min on password login, 10/min on WebAuthn login. Includes shared rate limiter reset fixture for tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
23ca6272a2
commit
d4acb46cf5
5 changed files with 52 additions and 0 deletions
|
|
@ -6,6 +6,7 @@ from httpx import ASGITransport, AsyncClient
|
|||
|
||||
from porchlight.app import create_app
|
||||
from porchlight.config import Settings
|
||||
from porchlight.rate_limit import limiter
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -21,6 +22,12 @@ async def client(settings: Settings) -> AsyncIterator[AsyncClient]:
|
|||
yield ac
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _reset_rate_limiter() -> None:
|
||||
"""Reset the rate limiter storage before each test."""
|
||||
limiter.reset()
|
||||
|
||||
|
||||
async def get_csrf_token(client: AsyncClient) -> str:
|
||||
"""Get a CSRF token by visiting the login page.
|
||||
|
||||
|
|
|
|||
25
tests/test_rate_limit.py
Normal file
25
tests/test_rate_limit.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import pytest
|
||||
from httpx import AsyncClient
|
||||
|
||||
from tests.conftest import get_csrf_token
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_password_login_rate_limited(client: AsyncClient) -> None:
|
||||
"""After 5 failed attempts, the 6th should be rate-limited."""
|
||||
token = await get_csrf_token(client)
|
||||
|
||||
for _ in range(5):
|
||||
await client.post(
|
||||
"/login/password",
|
||||
data={"username": "nobody", "password": "wrong"},
|
||||
headers={"X-CSRF-Token": token},
|
||||
)
|
||||
|
||||
response = await client.post(
|
||||
"/login/password",
|
||||
data={"username": "nobody", "password": "wrong"},
|
||||
headers={"X-CSRF-Token": token},
|
||||
)
|
||||
|
||||
assert response.status_code == 429
|
||||
Loading…
Add table
Add a link
Reference in a new issue