Résolution des erreurs HTTP 401 dans les tests de charge

Problème identifié

Les tests de charge retournaient 99% d’erreurs HTTP 401 Unauthorized :

Total requests: 52042
Successful: 494
Errors: 51548
Non-2xx or 3xx responses: 51509

Cause racine

L’architecture hexagonale de KoproGo implémente une authentification JWT obligatoire pour tous les endpoints CRUD via le middleware AuthenticatedUser (voir backend/src/infrastructure/web/middleware.rs).

Les scripts Lua originaux (mixed.lua, buildings.lua) ne fournissaient aucun token JWT dans leurs requêtes, ce qui causait les 401.

Endpoints concernés

Protégés (nécessitent JWT) :

  • /api/v1/buildings (GET, POST, PUT, DELETE)

  • /api/v1/units (GET, POST, PUT)

  • /api/v1/owners (GET, POST, PUT)

  • /api/v1/expenses (GET, POST, PUT)

  • /api/v1/meetings (GET, POST, PUT, DELETE)

  • /api/v1/documents (GET, POST, DELETE)

Publics (pas de JWT requis) :

  • /api/v1/health

  • /api/v1/auth/login

  • /api/v1/auth/register

  • /api/v1/auth/refresh

Solution implémentée

1. Nouveau script Lua : authenticated-mixed.lua

Ce script :

  1. Se connecte d’abord avec les credentials de démo

  2. Extrait le token JWT de la réponse

  3. Réutilise ce token pour toutes les requêtes suivantes

-- Première requête : login
local login_body = '{"email":"syndic@grandplace.be","password":"syndic123"}'
return wrk.format("POST", "/api/v1/auth/login", nil, login_body)

-- Requêtes suivantes : avec token
wrk.headers["Authorization"] = "Bearer " .. jwt_token

2. Comptes de démonstration utilisés

Credentials disponibles (voir backend/src/infrastructure/database/seed.rs:493-497) :

Organisation

Email

Mot de passe

Rôle

SuperAdmin

admin@koprogo.com

admin123

superadmin

Grand Place

syndic@grandplace.be

syndic123

syndic

Copro Bruxelles

syndic@copro-bruxelles.be

syndic123

syndic

Syndic Liège

syndic@syndic-liege.be

syndic123

syndic

Le script utilise par défaut : syndic@grandplace.be / syndic123

3. Scripts mis à jour

Les scripts suivants utilisent maintenant authenticated-mixed.lua :

  • load-tests/scripts/light-load.sh

  • load-tests/scripts/medium-load.sh

  • load-tests/scripts/heavy-load.sh

Comment vérifier que ça fonctionne

Test rapide local

# 1. Démarrer le backend avec données de démo
cd backend
cargo run

# 2. Dans un autre terminal, lancer un test light
cd load-tests
./scripts/light-load.sh

# 3. Vérifier dans la sortie :
# ✅ JWT token acquired successfully
# Total requests: ~12000
# Successful: ~11900+
# Errors: < 100

Test sur VPS

export BASE_URL=https://api.koprogo.com
./scripts/light-load.sh

Résultats attendus APRÈS le fix

Total requests: 12000
Successful: 11950+  (> 99%)
Errors: < 50        (< 1%)
✅ Authentication: SUCCESS

Alternatives considérées

Option 1 : Tests sans authentification (non retenue)

  • Tester uniquement /api/v1/health

  • ❌ Ne teste pas la logique métier réelle

  • ❌ Ne reflète pas l’usage en production

Option 2 : Désactiver l’auth temporairement (non retenue)

  • Modifier le middleware pour bypasser JWT en dev

  • ❌ Divergence entre dev et production

  • ❌ Risque de déployer sans auth par erreur

Option 3 : Authentification par script Lua ✅ (implémentée)

  • Authentification réaliste

  • ✅ Teste le flow complet incluant JWT

  • ✅ Reflète l’usage production

Code modifié

Fichiers créés

  • load-tests/lua/authenticated-mixed.lua - Script Lua avec JWT

Fichiers modifiés

  • load-tests/scripts/light-load.sh - Utilise authenticated-mixed.lua

  • load-tests/scripts/medium-load.sh - Utilise authenticated-mixed.lua

  • load-tests/scripts/heavy-load.sh - Utilise authenticated-mixed.lua

Fichiers inchangés (legacy)

  • load-tests/lua/mixed.lua - Conservé pour référence

  • load-tests/lua/buildings.lua - Conservé pour référence

  • load-tests/lua/auth.lua - Conservé pour tests d’auth spécifiques

Dépendances

Le script authenticated-mixed.lua nécessite :

  • LuaJIT avec module cjson (pour parser le JSON de réponse)

  • Installé automatiquement avec wrk sur la plupart des systèmes

Vérification :

wrk --version
# wrk 4.2.0 [epoll] Copyright (C) 2012 Will Glozer

Références

  • Middleware auth : backend/src/infrastructure/web/middleware.rs:32-72

  • Seed data : backend/src/infrastructure/database/seed.rs:493-497

  • Routes protégées : backend/src/infrastructure/web/routes.rs

  • Documentation JWT : backend/docs/JWT_SECURITY.md

Monitoring recommandé

Pour vérifier que l’authentification fonctionne en production :

# Logs backend pendant le test
docker compose logs -f backend | grep -i "401\|unauthorized\|token"

# Statistiques de réponses HTTP
docker compose logs backend | grep -oP 'status=\d+' | sort | uniq -c

Utilisation de run-all-tests.sh

Sur api2.koprogo.com

cd load-tests
export BASE_URL=https://api2.koprogo.com
./run-all-tests.sh

Sur api.koprogo.com (défaut)

cd load-tests
./run-all-tests.sh  # Utilise api.koprogo.com par défaut

En local

cd load-tests
export BASE_URL=http://localhost:8080
./run-all-tests.sh

Erreurs 404 courantes

Si vous obtenez des erreurs 404 :

  1. Vérifiez que BASE_URL est exporté :

    echo $BASE_URL  # Doit afficher https://api2.koprogo.com
    
  2. Vérifiez que les données de démo sont présentes :

    curl https://api2.koprogo.com/api/v1/health
    # Doit retourner 200 OK
    
    curl -X POST https://api2.koprogo.com/api/v1/auth/login \
      -H "Content-Type: application/json" \
      -d '{"email":"syndic@grandplace.be","password":"syndic123"}'
    # Doit retourner un token JWT
    
  3. Si login échoue = données de démo manquantes :

    • Connectez-vous en tant que superadmin

    • Appelez POST /api/v1/seed/demo


Date de résolution : 2025-10-25 Auteur : Claude Code Impact : Critique - Bloquait tous les tests de charge