94 lines
2.8 KiB
Markdown
94 lines
2.8 KiB
Markdown
# É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
|
||
```
|