# Corrections structurées : 401 et token manquant sur les requêtes API ## 1. Diagnostic (symptômes observés) - **Logs** : `DIO: Aucun token pour /api/membres`, `/api/cotisations/mes-cotisations/en-attente`, `/api/adhesions`, `/api/notifications/membre/...` - **Effet** : Toutes les requêtes API (membres, cotisations, adhésions, notifications) reçoivent **401 Unauthorized**. - **Constat** : L’utilisateur est bien authentifié (log « Token rafraîchi avec succès », « Utilisateur authentifié: Membre MUKEFI »), mais le client HTTP n’envoie jamais le Bearer token. ## 2. Cause racine Deux instances **différentes** de `FlutterSecureStorage` sont utilisées : | Composant | Configuration stockage | |------------------------|-------------------------| | **KeycloakAuthService** | `FlutterSecureStorage(aOptions: AndroidOptions(encryptedSharedPreferences: true), iOptions: IOSOptions(...))` | | **DioClient** | `FlutterSecureStorage()` (défaut) | Sur Android, une configuration avec `encryptedSharedPreferences: true` et la configuration par défaut ne partagent pas le même espace de stockage. Les tokens écrits par Keycloak après login/refresh sont donc **invisibles** pour l’intercepteur Dio, qui lit un stockage vide → « Aucun token ». ## 3. Correction appliquée ### 3.1 Unifier la configuration du stockage (DioClient) **Fichier** : `lib/core/network/dio_client.dart` - Utiliser la **même** configuration que `KeycloakAuthService` pour `FlutterSecureStorage` : - Android : `AndroidOptions(encryptedSharedPreferences: true)` - iOS : `IOSOptions(accessibility: KeychainAccessibility.first_unlock_this_device)` Ainsi, lecture et écriture des clés `keycloak_access_token`, `keycloak_refresh_token`, etc. se font dans le **même** stockage que celui utilisé par l’auth. ### 3.2 Vérifications connexes (déjà en place) - **Clés** : DioClient lit `keycloak_access_token` puis `keycloak_webview_access_token` ; KeycloakAuthService écrit bien dans `keycloak_access_token` (flux password) et dans le refresh Dio. - **Log diagnostic** : Le log « DIO: Auth token présent / Aucun token pour … » reste utile pour vérifier que le token est bien lu après correction. ## 4. Résumé des fichiers modifiés | Fichier | Modification | |---------|-------------| | `lib/core/network/dio_client.dart` | Utiliser un `FlutterSecureStorage` avec `AndroidOptions(encryptedSharedPreferences: true)` et `IOSOptions(accessibility: KeychainAccessibility.first_unlock_this_device)` (aligné sur KeycloakAuthService). | | `lib/core/network/api_client.dart` | Idem : lire le token depuis le même type de stockage pour les modules DRY (Feed, Explore, etc.). | ## 5. Après correction - Redémarrer l’app (full restart), se reconnecter si besoin. - Ouvrir les écrans : Membres, Cotisations, Adhésions, Notifications. - Dans les logs : `DIO: Auth token présent pour /api/...` et plus de 401 sur ces endpoints (sous réserve que le backend accepte le JWT). ## 6. Évolution possible - Centraliser la création du `FlutterSecureStorage` « auth » dans un seul module (ex. `lib/core/storage/` ou config partagée) et l’injecter / l’utiliser à la fois dans KeycloakAuthService et DioClient pour éviter toute divergence future.