179 lines
6.1 KiB
Markdown
179 lines
6.1 KiB
Markdown
# Étape 2 — OAuth2 Intra + token unique
|
||
|
||
> **Prérequis :** étape 1 OK (`swiftyCompanion/swifty_companion/` créé, `flutter run` fonctionne).
|
||
|
||
## Objectif de l’étape
|
||
|
||
1. Obtenir un **access token** via **OAuth2 de l’Intra** (pas un token par requête API).
|
||
2. Stocker les secrets dans **`.env`** (racine `swiftyCompanion/` ou dossier `swifty_companion/` — un seul endroit, documenté dans le README).
|
||
3. Avoir un **service d’auth** réutilisable pour toutes les futures requêtes `api.intra.42.fr`.
|
||
|
||
Les **vues** (recherche login, profil) viennent aux étapes 3–4 ; ici on pose l’authentification API.
|
||
|
||
---
|
||
|
||
## 2.1 — Vérifier l’app
|
||
|
||
```bash
|
||
cd ~/projets/42School/swifty_companion/swiftyCompanion/swifty_companion
|
||
flutter pub get
|
||
flutter run -d <device>
|
||
```
|
||
|
||
L’écran compteur par défaut suffit pour valider l’étape 1.
|
||
|
||
---
|
||
|
||
## 2.2 — Créer l’application OAuth sur l’Intra
|
||
|
||
1. [profile.intra.42.fr/oauth/applications](https://profile.intra.42.fr/oauth/applications) → **New application**.
|
||
2. Renseigner :
|
||
- **Name** : ex. `swifty_companion_dev`
|
||
- **Website** : URL factice ou repo perso (souvent requis)
|
||
- **Redirect URI** : doit correspondre **exactement** à ce que l’app utilisera (voir 2.3)
|
||
3. Noter **UID** (= `CLIENT_ID`) et **SECRET** (= `CLIENT_SECRET`).
|
||
|
||
Copier `swiftyCompanion/.env.example` → `.env` (même niveau que le README rendu ou dans `swifty_companion/`) :
|
||
|
||
```env
|
||
CLIENT_ID=...
|
||
CLIENT_SECRET=...
|
||
REDIRECT_URI=...
|
||
```
|
||
|
||
---
|
||
|
||
## 2.3 — Choisir le `REDIRECT_URI` (mobile)
|
||
|
||
### Erreur Intra : « must be a valid URI »
|
||
|
||
Le formulaire **42 Intra** accepte en pratique surtout des URI **`http://` ou `https://`**.
|
||
Les schémas du type `com.example.swifty_companion://callback` sont souvent **refusés** (validateur strict + `_` dans le schéma).
|
||
|
||
**Type d’application Intra :** `42 pedagogic project` (normal pour Swifty Companion — pas de type « mobile »).
|
||
|
||
**URI de redirection** — format **http(s)://host:port/chemin** uniquement (pas de `com.example://…`).
|
||
|
||
Essayer **dans cet ordre** (une seule ligne dans le champ, sans guillemets ni espace) :
|
||
|
||
1. `http://localhost:8080/callback` ← le plus courant sur l’Intra 42
|
||
2. `http://localhost:3000/callback`
|
||
3. `http://127.0.0.1:8080/callback`
|
||
|
||
Exemple tiré de la [doc 42](https://api.intra.42.fr/apidoc/guides/web_application_flow) :
|
||
`http://localhost:1919/users/auth/ft/callback` (tu peux t’en inspirer, mais garde une URI simple type `/callback`).
|
||
|
||
Copier **exactement** la ligne acceptée dans `.env` et dans Flutter.
|
||
|
||
Avec `flutter_appauth`, Android/iOS interceptent cette URL de boucle locale après le login dans le navigateur — pas besoin d’un vrai serveur web.
|
||
|
||
| Approche | Redirect URI | Intra 42 |
|
||
|----------|--------------|----------|
|
||
| **Recommandé (Flutter + 42)** | `http://127.0.0.1:42800/callback` | ✅ en général accepté |
|
||
| Schéma custom | `com.example.swifty_companion://callback` | ❌ souvent refusé |
|
||
| Site web classique | `https://ton-domaine.com/callback` | ✅ si tu as un backend |
|
||
|
||
Le même URI doit être : formulaire Intra, `.env`, et paramètre `redirect_uri` dans l’app.
|
||
|
||
**Android** : `applicationId` = `com.example.swifty_companion` (`android/app/build.gradle.kts`) — indépendant du `REDIRECT_URI` loopback.
|
||
|
||
Endpoints 42 (référence) :
|
||
|
||
| Étape | URL |
|
||
|-------|-----|
|
||
| Autorisation | `GET https://api.intra.42.fr/oauth/authorize` |
|
||
| Token | `POST https://api.intra.42.fr/oauth/token` |
|
||
| API | `GET https://api.intra.42.fr/v2/...` avec header `Authorization: Bearer <token>` |
|
||
|
||
Paramètres authorize usuels : `client_id`, `redirect_uri`, `response_type=code`, `scope=public`.
|
||
|
||
---
|
||
|
||
## 2.4 — Dépendances Flutter suggérées
|
||
|
||
Dans `swifty_companion/` :
|
||
|
||
```bash
|
||
flutter pub add flutter_dotenv http
|
||
# selon le flux choisi, par ex. :
|
||
# flutter pub add flutter_appauth
|
||
```
|
||
|
||
| Package | Rôle |
|
||
|---------|------|
|
||
| `flutter_dotenv` | Charger `.env` au démarrage |
|
||
| `http` | Échange code → token + appels API |
|
||
| `flutter_appauth` | Flux OAuth2 + redirect natif (optionnel mais pratique) |
|
||
|
||
---
|
||
|
||
## 2.5 — Architecture minimale (fichiers à créer)
|
||
|
||
```
|
||
lib/
|
||
├── main.dart # dotenv.load + MaterialApp
|
||
├── config/
|
||
│ └── env.dart # lecture CLIENT_ID, etc.
|
||
└── services/
|
||
└── intra_auth_service.dart # token en mémoire (singleton)
|
||
```
|
||
|
||
Règles sujet :
|
||
|
||
- **Un seul token** : le service le garde après le login OAuth ; les futures requêtes réutilisent `getAccessToken()`.
|
||
- **Ne pas** appeler `/oauth/token` avant chaque `GET /v2/users/...`.
|
||
|
||
Pseudo-contrat du service :
|
||
|
||
```dart
|
||
class IntraAuthService {
|
||
String? _accessToken;
|
||
String? get accessToken => _accessToken;
|
||
bool get isAuthenticated => _accessToken != null;
|
||
|
||
Future<void> signIn(); // ouvre le flux OAuth, stocke le token
|
||
Future<String> getValidToken(); // retourne le token (bonus : refresh plus tard)
|
||
}
|
||
```
|
||
|
||
Test manuel étape 2 : bouton « Se connecter à l’Intra » → navigateur / WebView → retour app → afficher temporairement « Connecté » ou le login `/v2/me`.
|
||
|
||
---
|
||
|
||
## 2.6 — `.env` et assets
|
||
|
||
Si `flutter_dotenv` charge depuis la racine du package Flutter :
|
||
|
||
1. Placer `.env` dans `swifty_companion/` (ignoré par git).
|
||
2. Déclarer dans `pubspec.yaml` :
|
||
|
||
```yaml
|
||
flutter:
|
||
assets:
|
||
- .env
|
||
```
|
||
|
||
> En production soutenance : les correcteurs créent **leur** `.env` avec **leur** app OAuth ; ne jamais committer le fichier.
|
||
|
||
---
|
||
|
||
## 2.7 — Critère « terminé » pour l’étape 2
|
||
|
||
| Check | OK si |
|
||
|-------|--------|
|
||
| OAuth Intra | Connexion obtient un access token |
|
||
| Token unique | Plusieurs appels API utilisent le **même** token sans re-login |
|
||
| Secrets | Uniquement dans `.env`, pas dans le code en dur |
|
||
| Doc | README rendu rappelle où mettre `.env` et comment lancer l’app |
|
||
|
||
---
|
||
|
||
## Ensuite — étape 3
|
||
|
||
→ [etape-03-vue-recherche.md](etape-03-vue-recherche.md) (à rédiger quand l’étape 2 est validée) : **vue 1** — champ login, appel API, erreurs 404 / réseau.
|
||
|
||
Documentation API utile :
|
||
|
||
- [apidoc](https://api.intra.42.fr/apidoc)
|
||
- User : `GET /v2/users/:id` ou recherche par login (voir doc)
|