# Étape 7 — Bonus : refresh token > **Prérequis :** partie obligatoire validée ([étape 6](etape-06-checklist-soutenance.md)). ## Objectif sujet Quand l’**access token** expire, l’app **rafraîchit** la session via le **refresh token** et continue à fonctionner **sans** relancer l’écran OAuth à chaque requête. --- ## Implémentation (ce dépôt) | Élément | Fichier | |---------|---------| | Stockage `access` + `refresh` après login | `intra_auth_service.dart` | | `POST /oauth/token` `grant_type=refresh_token` | `IntraAuthService.refreshAccessToken()` | | Un seul refresh en parallèle | `_refreshInFlight` (évite 4 refresh si 4 GET en 401) | | Sur **401** API → refresh → **rejouer** le GET | `intra_http.dart` → `intraApiGet(..., auth:)` | | Parsing JSON token | `intra_oauth_tokens.dart` | Les scopes OAuth restent `public` + `projects` à la connexion initiale. --- ## Flux ```text signIn() → access + refresh en mémoire GET /v2/users/... → 401 → refreshAccessToken() → nouveaux tokens → même GET avec nouveau Bearer sinon → IntraUnauthorizedException (« Reconnecte-toi ») ``` `signOut()` efface les deux tokens. **Persistance** (secure storage) : non fait — le bonus du sujet vise surtout l’expiration **pendant** une session ; tu peux l’ajouter plus tard. --- ## Tests automatisés ```bash cd swiftyCompanion/swifty_companion flutter test ``` - `test/intra_oauth_tokens_test.dart` — parsing réponse `/oauth/token` - `test/widget_test.dart` — démarrage app --- ## Test manuel (soutenance bonus) 1. Connexion 42 → recherche OK. 2. **Simuler** un access token expiré : - en debug, appeler une recherche après avoir invalidé le token en mémoire **sans** effacer le refresh (voir ci‑dessous), **ou** - attendre l’expiration réelle (souvent long). 3. Nouvelle recherche → refresh silencieux → profil OK **sans** repasser par le navigateur OAuth. ### Test sur device (build debug) Sur l’écran recherche, bouton **« DEBUG : simuler token expiré »** (`kDebugMode` uniquement — absent en release). 1. Connexion 42 OK. 2. Appuyer sur le bouton debug. 3. **Rechercher** un login → refresh silencieux → profil OK sans repasser par OAuth. En release / soutenance APK release : expliquer le flux ou montrer `flutter test`. --- ## Critères « bonus OK » | # | Test | |---|------| | 1 | 401 sur API → refresh → requête réussie | | 2 | Refresh impossible → message « session expirée », pas de crash | | 3 | `flutter test` vert | --- ## Fichiers modifiés (récap) ``` lib/services/ ├── intra_auth_service.dart # refresh + stockage refresh_token ├── intra_http.dart # 401 → refresh → retry ├── intra_oauth_tokens.dart # parse JSON token └── … (user / profile passent auth à intraApiGet) test/intra_oauth_tokens_test.dart ```