feat(security): rate limiting /api/v1/auth/login — HRT-62 #6

Open
admin wants to merge 0 commits from feature/HRT-62-rate-limiting-login into master
Owner

Fix brute force sur /api/v1/auth/login

Ticket: HRT-62

Changements

saas_auth.py

  • Ajout rate limiter in-memory IP-based dans la route login()
  • 5 tentatives max / 5 min par IP (fenêtre glissante)
  • Blocage 15 min après dépassement
  • Retourne 429 + header Retry-After
  • Uniquement stdlib: collections.defaultdict, threading.Lock, time

portal_server.py

  • Import et enregistrement de rate_limit_middleware + access_log_middleware
  • Ces middlewares existaient dans middleware.py mais n'étaient pas appliqués sur portal_server.py

tests/security/test_security.py

  • Ajout de TestLoginRateLimit avec 2 tests :
    • test_login_brute_force_blocked_after_5_attempts
    • test_login_429_has_retry_after_header

Tests

  • 61 passed, 3 skipped (tests e2e sans fixtures)
  • 1 test integration échoue car il frappe le serveur live qui n'a pas encore été redémarré avec le nouveau code (attendu - restart après validation CTO uniquement)

Action requise

Après merge, redémarrer le service portal (systemctl/pm2) pour activer le fix.

## Fix brute force sur /api/v1/auth/login **Ticket:** HRT-62 ### Changements #### `saas_auth.py` - Ajout rate limiter in-memory IP-based dans la route `login()` - 5 tentatives max / 5 min par IP (fenêtre glissante) - Blocage 15 min après dépassement - Retourne 429 + header `Retry-After` - Uniquement stdlib: `collections.defaultdict`, `threading.Lock`, `time` #### `portal_server.py` - Import et enregistrement de `rate_limit_middleware` + `access_log_middleware` - Ces middlewares existaient dans `middleware.py` mais n'étaient pas appliqués sur `portal_server.py` #### `tests/security/test_security.py` - Ajout de `TestLoginRateLimit` avec 2 tests : - `test_login_brute_force_blocked_after_5_attempts` - `test_login_429_has_retry_after_header` ### Tests - 61 passed, 3 skipped (tests e2e sans fixtures) - 1 test integration échoue car il frappe le serveur live qui n'a pas encore été redémarré avec le nouveau code (attendu - restart après validation CTO uniquement) ### Action requise Après merge, redémarrer le service portal (systemctl/pm2) pour activer le fix.
admin added 2 commits 2026-04-27 14:50:46 +02:00
- Ajout tests/test_ml_cache_integrity.py : 7 tests integration vérifiant
  que hippodrome, race_label et heure ne sont pas NULL pour la date courante
- Ajout marqueur 'integration' dans pytest.ini
- Connexion DB en lecture seule (mode=ro) pour protection prod
- Support variable d'env TEST_DATE et TURF_DB_PATH
- Tests skippés proprement si job 19h30 n'a pas encore tourné
- Validé sur les données 2026-04-26 : 7/7 PASSED (1005 lignes, 0 NULL)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- saas_auth.py: in-memory sliding-window rate limiter (5 attempts/5min, 15min block)
  using collections.defaultdict + threading.Lock, stdlib only, no new deps
- portal_server.py: register rate_limit_middleware + access_log_middleware
  (was missing, leaving global 100req/min limit unApplied on portal routes)
- tests/security/test_security.py: add TestLoginRateLimit class with
  test_login_brute_force_blocked_after_5_attempts and test_login_429_has_retry_after_header

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This branch is already included in the target branch. There is nothing to merge.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feature/HRT-62-rate-limiting-login:feature/HRT-62-rate-limiting-login
git checkout feature/HRT-62-rate-limiting-login
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: admin/turf_saas#6