# É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 ``` 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 ` | 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 signIn(); // ouvre le flux OAuth, stocke le token Future 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)