From f00cf0f833e3667f3d2571185710321196f98afa Mon Sep 17 00:00:00 2001 From: Antoine Van Elstraete Date: Tue, 8 Sep 2026 23:03:09 +0200 Subject: [PATCH] =?UTF-8?q?Ajouter=20section=20authentification=20QR=20cod?= =?UTF-8?q?e=20/=20token,=20corriger=20note=20obsol=C3=A8te?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GuidePronote.md | 272 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 GuidePronote.md diff --git a/GuidePronote.md b/GuidePronote.md new file mode 100644 index 0000000..401acb4 --- /dev/null +++ b/GuidePronote.md @@ -0,0 +1,272 @@ +# Guide-Pronote + +Ce guide pratique explique comment configurer les variables spécifiques à **Pronote** pour le pipeline `pronote-sync`. +Pour un tableau complet des variables disponibles, consultez la page [Configuration](Configuration). + +--- + +## Obtenir l'URL iCal (`PRONOTE_ICAL_URL`) + +L'URL iCal est le flux d'export du calendrier Pronote. Elle contient un **token `icalsecurise`** sensible et doit être traitée comme un mot de passe. + +### Étapes pour obtenir l'URL iCal : +1. Se connecter à l'espace **parent** Pronote. +2. Aller dans la vue **Emploi du temps** (souvent accessible via *Vie scolaire* ou le widget calendrier). +3. Chercher l'icône d'export agenda / synchronisation calendrier (généralement en haut à droite de l'emploi du temps, libellée **« Exporter »** ou **« Synchroniser avec un agenda »**). +4. Une fenêtre modale affiche l'**URL d'abonnement iCal**. + +### Format attendu : +```text +https://.index-education.net/pronote/ical/Edt_Prenom.ics?icalsecurise=&version=2024 +``` + +### Avertissements : +- Le token `icalsecurise` est **sensible** : il est stocké en `SecretStr` et masqué dans les logs. +- Certaines instances Pronote **ne proposent pas** d'export iCal. Si la page d'agenda ne montre que les options **« Personnaliser »** et **« Générer un PDF pour impression »**, l'iCal n'est pas disponible. Dans ce cas, laissez `PRONOTE_ICAL_URL` vide et utilisez `pronotepy` comme source unique. + +--- + +## Obtenir l'URL de connexion (`PRONOTE_URL`) + +`PRONOTE_URL` est l'URL de la page Pronote utilisée par [`pronotepy`](https://github.com/bain3/pronotepy) pour la connexion API. + +### Contraintes : +- C'est l'URL **visible dans le navigateur** sur la page de connexion Pronote, **sans paramètres de requête**. +- **Format** : + ```text + https://.index-education.net/pronote/parent.html + ``` +- Retirez **tout paramètre de query string** (ex. `?identifiant=...`). `pronotepy` ne supporte pas les paramètres de requête dans cette URL. + +### Note importante : +`PRONOTE_URL` et `PRONOTE_ICAL_URL` sont **deux contrats distincts** : l'un ne doit **jamais** être déduit de l'autre. + +--- + +## Type de compte (`PRONOTE_ACCOUNT_TYPE`) + +- **Valeur par défaut** : `parent`. +- Le projet utilise : + - `pronotepy.ParentClient` pour un compte **parent**. + - `pronotepy.Client` pour un compte **élève**. +- Pour un compte parent, conservez la valeur par défaut. + +--- + +## Identifiants (`PRONOTE_USERNAME` et `PRONOTE_PASSWORD`) + +- **`PRONOTE_USERNAME`** : Identifiant de connexion à l'espace parent Pronote. +- **`PRONOTE_PASSWORD`** : Mot de passe associé. + - Le mot de passe est stocké en `SecretStr` et **masqué dans les logs et les erreurs**. + +--- + +## ENT (`PRONOTE_ENT`) + +Si votre collège utilise un **ENT** (Espace Numérique de Travail) pour la connexion à Pronote, renseignez le **slug** correspondant. + +### Fonctionnement : +- Le projet résout ce slug vers une fonction de `pronotepy.ent` via une **liste fermée**. +- Si la connexion est **directe** (pas de redirection ENT), laissez `PRONOTE_ENT` **vide ou absent**. + +### Quand l'ENT est obligatoire + +De nombreuses instances Pronote délèguent l'authentification à un fournisseur d'identité externe (EduConnect, HubEduConnect, SSO SAML). Dans ce cas, `pronotepy` ne peut pas s'authentifier directement avec uniquement un nom d'utilisateur et un mot de passe : il a besoin du résolveur ENT pour gérer le flux d'authentification et fournir les cookies de session nécessaires. + +**Comment savoir si votre instance nécessite un ENT :** +- Si vous obtenez l'erreur `Page html is different than expected. Be sure that pronote_url is the direct url to your pronote page.`, cela signifie presque certainement que votre instance Pronote redirige vers un portail d'authentification (EduConnect/HubEduConnect) et que vous devez configurer `PRONOTE_ENT`. +- Essayez d'ouvrir votre `PRONOTE_URL` dans un navigateur en mode navigation privée/incognito. Si vous êtes redirigé vers une page de connexion EduConnect ou ENT, vous devez configurer l'ENT. + +**Académie de Bordeaux (HubEduConnect) :** +- L'académie de Bordeaux utilise HubEduConnect (via EduConnect) pour l'authentification. +- Configuration : `PRONOTE_ENT=bordeaux` +- Le résolveur `bordeaux` gère le flux HubEduConnect sur `hubeduconnect.index-education.net`. + +**Autres instances EduConnect :** +- De nombreuses académies utilisent EduConnect. Si votre instance redirige vers `educonnect.education.gouv.fr` ou `hubeduconnect.index-education.net`, recherchez le slug correspondant dans le tableau ci-dessous. +- Si votre académie n'est pas listée, la connexion peut ne pas être supportée par `pronotepy` pour le moment. + +> **Note** : Si l'authentification via ENT échoue (en raison de CAPTCHA, de MFA ou d'un flux d'authentification modifié), `pronotepy` prend également en charge la connexion par **code QR / token** comme alternative. Voir la section [Authentification par QR code / token](#authentification-par-qr-code--token-pronote_auth_mode-qr_token) ci-dessous. + +### Slugs ENT supportés : + +| Slug | ENT | +|------|-----| +| `monbureaunumerique` | Mon Bureau Numérique | +| `ent_elyco` | ENT Elyco | +| `bordeaux` | ENT Bordeaux | +| `ent_creuse` | ENT Creuse | +| `occitanie_montpellier` | Occitanie Montpellier | +| `paris_classe_numerique` | Paris Classe Numérique | +| `ile_de_france` | Île-de-France | +| `ent_hdf` | ENT Hauts-de-France | +| `ac_orleans_tours` | Académie Orléans-Tours | +| `ac_poitiers` | Académie Poitiers | +| `ac_rennens` | Académie Rennes | +| `laclasse_educonnect` | LaClasse (EduConnect) | +| `ent77` | ENT 77 | +| `ent_ecollege78` | eCollège 78 | +| `ent_essonne` | ENT Essonne | +| `val_doise` | Val d'Oise | +| `val_de_marne` | Val de Marne | +| `ent_var` | ENT Var | +| `atrium_sud` | Atrium Sud | +| `laclasse_lyon` | LaClasse Lyon | +| `eclat_bfc` | ÉCLAT Bourgogne-Franche-Comté | +| `cas_arsene76` | CAS Arsène 76 | +| `cas_ent27` | CAS ENT 27 | +| `cas_kosmos` | CAS Kosmos | +| `ent_creuse_educonnect` | ENT Creuse (EduConnect) | +| `ent_mayotte` | ENT Mayotte | +| `ent_somme` | ENT Somme | +| `ent_94` | ENT 94 | +| `extranet_colleges_somme` | Extranet Collèges Somme | +| `ac_reunion` | Académie Réunion | + +--- + +## Authentification par QR code / token (`PRONOTE_AUTH_MODE=qr_token`) + +Pour les instances Pronote utilisant **HubEduConnect/EduConnect** où l'authentification par mot de passe échoue (CAPTCHA, MFA, flux SAML modifié), le pipeline supporte l'authentification par **QR code puis token persistant**. +Ce mode est sélectionné via la variable `PRONOTE_AUTH_MODE=qr_token` (le mode par défaut reste `password`). + +### Enrôlement initial (premier login) + +1. **Générer un QR code** depuis l'application mobile Pronote (Android/iOS) : + - Ouvrir l'application Pronote → se connecter → aller dans les paramètres → **« Exporter un QR code »** (ou similaire). + - Le QR code est exporté sous forme de fichier JSON (ex. : `qr_code.json`). + - **⚠️ Le QR code expire environ 10 minutes après génération** — soyez rapide. + +2. **Configurer les variables** dans votre fichier `.env` : + ```ini + PRONOTE_AUTH_MODE=qr_token + PRONOTE_QR_CODE_FILE=/chemin/vers/qr_code.json + PRONOTE_QR_PIN=1234 + ``` + +3. **Lancer le pipeline** (ex. : `pronote-sync --dry-run` pour tester). + Au premier login : + - `pronotepy.qrcode_login(qr_code, pin, uuid)` est appelé avec le contenu du JSON et le PIN. + - Les *credentials* exportées par `pronotepy.export_credentials()` sont **persistées** dans `.pronote_auth_state.json` (permissions `0600`). + - Le QR code et le PIN **ne sont plus nécessaires** pour les exécutions suivantes. + +### Exécutions suivantes (token persisté) + +- Le pipeline charge le token depuis `.pronote_auth_state.json` et utilise `pronotepy.token_login(**credentials)`. +- Le token **rotate à chaque session** — le fichier `.pronote_auth_state.json` est mis à jour automatiquement après chaque login réussi. +- **Aucune action manuelle requise** tant que le token reste valide. + +### Ré-enrôlement manuel (rotation échouée) + +Si le token expire ou devient invalide (ex. : session révoquée côté serveur, fichier corrompu), une erreur `PronoteAuthRotationError` est levée. +Le pipeline : +- journalise l'erreur (**expurgée**, sans token ni PIN) ; +- envoie une **notification XMPP actionnable** si le canal est configuré et que `dry_run` est inactif ; +- retourne un résultat dégradé. + +**Pour ré-enrôler** : +1. Supprimer le fichier `.pronote_auth_state.json`. +2. Générer un **nouveau QR code** depuis l'application mobile Pronote. +3. Mettre à jour `PRONOTE_QR_CODE_FILE` et `PRONOTE_QR_PIN` si nécessaire. +4. Relancer le pipeline — l'enrôlement initial se déclenche automatiquement. + +### Sécurité + +- Le fichier `.pronote_auth_state.json` contient un **token d'authentification vivant** : + - Il est créé avec les permissions `0600` (lecture/écriture **uniquement par le propriétaire**). + - Il ne doit **jamais être committé** (couvert par `.gitignore`). + - Son contenu (token, URL, identifiant) ne doit **jamais apparaître** dans les logs, les messages d'erreur ou les notifications XMPP. +- Le PIN (`PRONOTE_QR_PIN`) est stocké en `SecretStr` et **masqué dans tous les logs**. + +### Exemple de configuration complet (mode `qr_token`) + +```ini +PRONOTE_AUTH_MODE=qr_token +PRONOTE_URL=https://0640036s.index-education.net/pronote/parent.html +PRONOTE_ACCOUNT_TYPE=parent +PRONOTE_QR_CODE_FILE=/path/to/qr_code.json +PRONOTE_QR_PIN=1234 + +# Sources (pronotepy uniquement — pas d'iCal sur cette instance) +PRONOTE_AGENDA_SOURCE=pronotepy +PRONOTE_HOMEWORK_SOURCE=pronotepy +PRONOTE_MESSAGES_SOURCE=pronotepy +``` + +--- + +## Choix des sources (`PRONOTE_AGENDA_SOURCE`, `PRONOTE_HOMEWORK_SOURCE`, `PRONOTE_MESSAGES_SOURCE`) + +Le pipeline propose trois modes pour récupérer les données Pronote : + +### Modes disponibles : +- **`auto`** (par défaut) : + Essaye d'abord **iCal**, puis bascule vers `pronotepy` **uniquement si iCal lève une exception**. +- **`ical`** : + Utilise **uniquement iCal**, sans bascule silencieuse. + **Requiert** `PRONOTE_ICAL_URL`. +- **`pronotepy`** : + Utilise **uniquement `pronotepy`**, sans bascule silencieuse. + **Requiert** `PRONOTE_URL`, `PRONOTE_USERNAME`, `PRONOTE_PASSWORD`, et `PRONOTE_ENT` (si applicable). + +### Comportements : +- En mode `auto`, si **iCal et `pronotepy` échouent** → **erreur critique explicite**. +- Une **liste vide** est un **succès valide** : elle ne doit pas être assimilée à une panne. +- Les **messages** ne sont disponibles que via `pronotepy` (absents du flux iCal). + **`PRONOTE_MESSAGES_SOURCE` est toujours `pronotepy`**. + +--- + +## Exemple sans iCal (pronotepy uniquement) + +Si votre instance Pronote ne propose pas d'export iCal, utilisez `pronotepy` comme source unique : + +```ini +PRONOTE_URL=https://0640036s.index-education.net/pronote/parent.html +PRONOTE_ACCOUNT_TYPE=parent +PRONOTE_USERNAME=parent.dupont +PRONOTE_PASSWORD=ton_mot_de_passe +PRONOTE_ENT=bordeaux + +# Sources : pronotepy uniquement (pas de repli iCal) +PRONOTE_AGENDA_SOURCE=pronotepy +PRONOTE_HOMEWORK_SOURCE=pronotepy +PRONOTE_MESSAGES_SOURCE=pronotepy +``` + +--- + +## Exemple avec iCal et pronotepy (mode auto) + +Si votre instance Pronote propose l'export iCal, vous pouvez utiliser le mode `auto` pour basculer automatiquement entre les sources : + +```ini +PRONOTE_ICAL_URL=https://.index-education.net/pronote/ical/Edt_Prenom.ics?icalsecurise=&version=2024 +PRONOTE_URL=https://.index-education.net/pronote/parent.html +PRONOTE_ACCOUNT_TYPE=parent +PRONOTE_USERNAME=parent.dupont +PRONOTE_PASSWORD=ton_mot_de_passe +PRONOTE_ENT=bordeaux + +PRONOTE_AGENDA_SOURCE=auto +PRONOTE_HOMEWORK_SOURCE=auto +PRONOTE_MESSAGES_SOURCE=pronotepy +``` + +--- + +## Tester la configuration + +Pour valider votre configuration Pronote, exécutez le pipeline en mode **simulation** : + +```bash +pronote-sync --dry-run --log-level DEBUG +``` + +- Le mode `--dry-run` valide la connexion et le pipeline **sans écrire** dans CalDAV/XMPP. +- Le niveau de log `DEBUG` affiche les **étapes détaillées** pour diagnostiquer d'éventuels problèmes. + +--- + +→ [Configuration](Configuration) — tableau des variables +→ [Sécurité](Sécurité) — gestion des secrets \ No newline at end of file