Files
college-infos/docs/pronote-auth.md
T
OpenCode 8efac8645b docs(auth): rendre la référence Pronote vérifiable
Qualifie sources et hypothèses (pronotepy 2.15.7, 2026-09-12), corrige le nombre d'ENT, exclut CAS/SAML/EduConnect générique, aligne la procédure QR sur .env.example et supprime les exemples copiables.

Refs #10
2026-09-12 19:18:28 +02:00

20 KiB
Raw Blame History

⚠️ AVERTISSEMENT

Ce document n'est pas un guide officiel. Il n'est ni approuvé, ni validé, ni autorisé par le Ministère de l'Éducation Nationale française ni par Docaposte (éditeur de Pronote / Index Éducation). Les informations présentées reposent sur :

  • des observations directes du code source de pronotepy (version 2.15.7, vérifiée localement le 2026-09-12) ;
  • des issues publiques du dépôt bain3/pronotepy (ex. #309, #344) ;
  • des tests d'intégration du projet pronote-sync.

⚠️ Note importante (2026-09-12) : Un essai réel sur l'instance Pronote cible est nécessaire avant tout usage en production. Les tests/mocks ne prouvent pas la compatibilité d'instance.

Convention de qualification : Observé dans le code local : Mécanisme vérifié dans le code source de pronotepy 2.15.7 ou pronote-sync. 🔍 Observé localement : Comportement constaté dans les interfaces Pronote (version non spécifiée, hypothèse à valider). ⚠️ Hypothèse à valider : Affirmation non vérifiée, nécessitant une confirmation par test sur une instance réelle.


Authentification Pronote — Référence technique pour pronote-sync

Introduction

Ce document documente uniquement les méthodes d'authentification prises en charge ou délégables par pronote-sync, en alignement strict avec :

  • Le code source de pronote_sync/sources/pronote/client.py (liste fermée _ENT_NAMES, gestion des tokens).
  • La bibliothèque pronotepy 2.15.7 (contrat des méthodes qrcode_login, token_login, export_credentials).
  • Les paramètres de configuration .env.example (lignes 2125).

Périmètre :

  • Pris en charge : Méthodes implémentées et testées dans pronote-sync.
  • Délégable à pronotepy : Méthodes gérées par pronotepy mais non directement exposées par pronote-sync.
  • Non implémenté : Méthodes non supportées (ex. CAS/SAML générique, EduConnect direct).

Public cible : Développeurs et intégrateurs de pronote-sync.


Tableau de compatibilité avec pronote-sync

Méthode Statut dans pronote-sync Implémentation Source Notes
URL iCal sécurisée (icalsecurise) Pris en charge Source ical (prioritaire en mode auto) 🔍 pronote_sync/sources/ical.py Jeton dans l'URL traité comme secret.
Connexion directe (mot de passe + ENT) Pris en charge Source pronotepy (repli si iCal échoue) 🔍 pronote_sync/sources/pronote/client.py Liste fermée _ENT_NAMES (lignes 5284).
QR Code + token mobile Pris en charge Mode PRONOTE_AUTH_MODE=qr_token 🔍 pronotepy.Client.qrcode_login + token_login Voir Procédure QR.
SSO ENT (CAS/SAML) Non implémenté Seuls les 30 ENT de la liste fermée _ENT_NAMES (pronotepy 2.15.7) sont supportés via ent dans ParentClient. Pas de SSO générique CAS/SAML.
EduConnect (HubEduConnect) Non implémenté Nécessite une intégration CAS/SAML générique, non supportée par ce projet.
CAS direct Non implémenté Non supporté.
API publique Inexistante Aucune API publique n'est utilisée/implémentée par ce projet ; aucune API officielle publique n'a été vérifiée à la date du 2026-09-12.

Méthode 1 : URL iCal sécurisée (icalsecurise)

Principe général

Pronote expose un flux de calendrier en lecture seule conforme à la norme iCalendar (RFC 5545). L'accès est contrôlé par un jeton secret intégré dans l'URL sous forme de paramètre de requête icalsecurise.

Statut : Observé localement (fonctionnalité native de Pronote, version non spécifiée).

Obtention du jeton

  1. Se connecter à Pronote (Espace Parents ou Élève) via n'importe quelle méthode.
  2. Accéder à la vue « Emploi du temps ».
  3. Utiliser la fonction « Export iCal » ou « Exporter ».
  4. Pronote génère une URL contenant un jeton secret icalsecurise.
  5. Copier cette URL : elle constitue une crédentiale unique sensible qui doit être protégée comme un mot de passe.

🔹 Source : 🔍 Observé localement dans les interfaces Pronote (version non spécifiée, hypothèse à valider). ⚠️ Note : Les étapes dépendent de l'instance et du type de compte. L'exemple ci-dessus est non fonctionnel et ne contient aucun secret.

Format de l'URL

https://{etablissement}.index-education.net/pronote/ical/Edt_{prenom}.ics?icalsecurise={jeton}&version={version}&param={param}
  • icalsecurise : Jeton secret (crédentiale).
  • version : Version de Pronote (ex. 2024).
  • param : Paramètres optionnels.

🔹 Source : 🔍 Analysé via pronote_sync/sources/ical.py.

Cycle de vie

  • Pérennité : Le jeton reste valide jusqu'à :
    • Révocation manuelle par l'utilisateur dans Pronote.
    • Régénération par l'établissement (ex. à la rentrée scolaire). ⚠️ Hypothèse à valider : La durée exacte dépend des politiques de l'établissement (non documentée officiellement).

🔹 Source : ⚠️ Comportement variable selon les instances (à tester localement).

Sécurité

  1. Surface d'attaque : Le jeton est encodé dans l'URL → risque d'exposition via :
    • Logs serveur/proxy.
    • En-tête Referer.
    • Historique du navigateur.
  2. Recommandations :
    • Ne jamais versionner l'URL (ex. dans .env ou Git).
    • Utiliser HTTPS (obligatoire).
    • Masquer l'URL dans les logs (ex. via redact_url() dans pronote-sync).

🔹 Source : ⚠️ Recommandation du projet (inspirée des bonnes pratiques générales de sécurité).

Intégration dans pronote-sync

  • Paramètre : PRONOTE_ICAL_URL (ex. .env.example ligne 2).
  • Comportement :
    • Prioritaire en mode PRONOTE_AGENDA_SOURCE=auto.
    • Si l'URL est invalide ou expire, repli automatique vers pronotepy (si PRONOTE_AGENDA_SOURCE=auto).
    • Aucun repli si PRONOTE_AGENDA_SOURCE=ical (échec explicite).

🔹 Source : 🔍 pronote_sync/config/settings.py + pronote_sync/sources/ical.py.


Méthode 2 : Connexion directe (identifiant / mot de passe + ENT)

Principe général

Connexion via le protocole propriétaire de Pronote (JSON sur HTTPS), avec chiffrement AES-CBC utilisant une clé dérivée par MD5 (16 octets, soit AES-128) comme implémenté dans pronotepy 2.15.7 et mécanisme de défi-réponse. Utilisé par l'interface web.

Statut : Observé dans le code local (délégable à pronotepy via ParentClient ou Client).

Flux d'authentification

  1. Initialisation : Requête GET vers /pronote/{espace}.html (ex. parent.html).
    • Récupère h (ID de session), a (ID espace), sCrA/sCoA (drapeaux chiffrement/compression).
  2. Échange de clés : Requête POST vers /pronote/appelfonction/{a}/{h}/{numeroOrdre}.
  3. Identification : Soumission de identifiant, genreConnexion=0, genreEspace={a}.
  4. Résolution du défi :
    • Calcul de mtp = MAJUSCULE(HEX(SHA256(alea + mot_de_passe))).
    • Dérivation de key_challenge = MD5(nom_utilisateur + mtp).
    • Déchiffrement du challenge avec AES-CBC utilisant une clé dérivée par MD5 (16 octets, soit AES-128).
  5. Authentification : Soumission de la réponse au défi.

🔹 Source : 🔍 Observé dans le code local de pronotepy 2.15.7 (module clients.py et pronoteAPI.py, vérifié le 2026-09-12).

Intégration dans pronote-sync

  • Paramètres :
    • PRONOTE_URL (ex. .env.example ligne 3).
    • PRONOTE_USERNAME, PRONOTE_PASSWORD.
    • PRONOTE_ENT (slug dans _ENT_NAMES).
    • PRONOTE_ACCOUNT_TYPE (ex. parent).
  • Comportement :
    • Utilise pronotepy.ParentClient pour les comptes parents.
    • Repli : Si iCal échoue en mode auto, pronotepy est utilisé.
    • Pas de repli si PRONOTE_AGENDA_SOURCE=pronotepy (échec explicite).

🔹 Source : 🔍 pronote_sync/sources/pronote/client.py (méthode _connect_password).

ENT supportés

Liste fermée des 30 ENT résolubles (lignes 5283 de pronote_sync/sources/pronote/client.py) :

_monbureaunumerique, ent_elyco, bordeaux, ent_creuse, occitanie_montpellier, ...

⚠️ Hypothèse à valider : Les ENT non listés nécessitent une contribution à pronotepy.

🔹 Source : 🔍 Code source local de pronote-sync (2026-09-12).


Méthode 3 : QR Code + token mobile (pour pronote-sync)

Principe général

Mécanisme d'appairage par QR code pour les appareils mobiles, contournant l'authentification ENT/EduConnect. Le QR code est généré depuis l'interface web Pronote, espace parent → paramètres → QR code, puis utilisé avec un PIN à 4 chiffres pour obtenir un token dont la durée dépend de l'instance/serveur.

Statut : Pris en charge par pronote-sync (mode PRONOTE_AUTH_MODE=qr_token).

Procédure QR pour pronote-sync

Étape 1 : Génération du QR code (interface web)

  1. Se connecter à Pronote via un navigateur (espace Parent).
  2. Aller dans Paramètres → Accès mobile / Application mobile.
  3. Définir un PIN temporaire à 4 chiffres.
  4. Pronote affiche un QR code contenant un JSON avec les clés : login, jeton, et url (ex. https://[host]/pronote/mobile.parent.html). Le fichier JSON réel contient des identifiants chiffrés et ne doit jamais être copié, partagé, ou committé.
  5. Exporter le QR code :
    • Sauvegardez le fichier JSON localement ou scannez-le avec un appareil.
    • Ne jamais partager le JSON ou le PIN.
    • Le fichier JSON du QR code contient des identifiants chiffrés : ne jamais le coller dans la documentation ni le committer.

🔹 Source : 🔍 Observé localement dans l'interface web Pronote (version non spécifiée, hypothèse à valider).

Étape 2 : Configuration de pronote-sync

  1. Enregistrer le QR code :
    • Sauvegarder le JSON dans un fichier (ex. /path/to/qr_code.json).
    • Permissions : chmod 600 /path/to/qr_code.json.
  2. Configurer .env :
    PRONOTE_AUTH_MODE=qr_token
    PRONOTE_QR_CODE_FILE=/path/to/qr_code.json
    PRONOTE_QR_PIN=  # renseigner localement la valeur secrète du PIN (jamais committée)
    
    ⚠️ Note : .env.example ne doit jamais contenir de PIN concret.

🔹 Source : 🔍 Observé dans .env.example (lignes 2125) et pronote_sync/sources/pronote/client.py.

Étape 3 : Premier login (enrôlement)

  1. pronote-sync lit PRONOTE_QR_CODE_FILE et PRONOTE_QR_PIN.
  2. Appel à pronotepy.ParentClient.qrcode_login(qr_code, pin, uuid) :
    • qr_code : JSON du fichier QR.
    • pin : PIN à 4 chiffres.
    • uuid : UUID permanent généré par pronote-sync (ex. pronote-sync-{uuid4()}).
  3. Déchiffrement :
    • Algorithme : AES-CBC utilisant une clé dérivée par MD5 (16 octets, soit AES-128).
    • Clé : MD5(PIN) (dérivée du PIN secret).
    • IV : 16 octets nuls.
    • Résultat : login et jeton en clair.
  4. Échange de token : Pronote retourne un jetonConnexionAppliMobile (token dont la durée dépend de l'instance/serveur).
  5. Persistance : pronote-sync sauvegarde les credentials via export_credentials() dans .pronote_auth_state.json (mode 0600).

🔹 Source : 🔍 Observé dans le code local de pronotepy 2.15.7 (clients.py lignes 181189) + pronote_sync/sources/pronote/client.py (méthode _enroll_qr_code).

Étape 4 : Connexions ultérieures (auto-login)

  1. pronote-sync charge .pronote_auth_state.json.
  2. Appel à pronotepy.ParentClient.token_login(**credentials) :
    • pronote_url, username, password (token), uuid.
  3. Rotation du token : Le token est remplacé uniquement si le serveur renvoie jetonConnexionAppliMobile (observé dans pronotepy 2.15.7, clients.py:382387).
  4. Persistance : Les credentials sont sauvegardés dans .pronote_auth_state.json après chaque opération réussie.

🔹 Source : 🔍 Observé dans le code local de pronotepy 2.15.7 (clients.py lignes 245280) + pronote_sync/sources/pronote/client.py (méthode _connect_qr_token).

Cycle de vie des tokens

  • QR code : Valide ~10 minutes après génération (⚠️ Hypothèse à valider : cette durée n'est attestée que par un message d'exception dans pronotepy et n'est pas une garantie officielle/indépendante de l'instance).
  • jetonConnexionAppliMobile :
    • Durée dépendante de l'instance/serveur (observation du 2026-09-12, hypothèse : peut persister jusqu'à la fin de l'année scolaire, non garanti).
    • Remplacé uniquement si le serveur renvoie jetonConnexionAppliMobile (observé dans pronotepy 2.15.7, clients.py:382387).
    • Révocable manuellement dans Pronote (Paramètres → Accès mobile).

🔹 Source : ⚠️ Comportement variable selon les instances (à tester localement).

Sécurité

  1. Fichiers sensibles :
    • .pronote_auth_state.json : Ne jamais versionner (couvert par .gitignore).
    • PRONOTE_QR_CODE_FILE : Ne jamais committer (ex. dans Git).
  2. Secrets :
    • Le PIN et le contenu du QR code sont masqués dans les logs (via redact_secrets()).
    • Les exceptions sont expurgées (via redact_exception()).
  3. Recommandations :
    • Utiliser un PIN robuste (éviter les codes simples comme 0000 ou des séquences évidentes).
    • Révoquer le token en cas de compromission (via Pronote web).

🔹 Source : 🔍 pronote_sync/utils/redaction.py + pronote_sync/sources/pronote/client.py (méthode _collect_auth_secrets).

Erreurs et repli

  • PronoteAuthRotationError : Levée si :
    • Le token persisté est invalide/expiré.
    • Le fichier QR ou le PIN est manquant/invalide.
  • Action requise :
    1. Supprimer .pronote_auth_state.json.
    2. Générer un nouveau QR code depuis l'interface web Pronote, espace parent.
    3. Relancer pronote-sync.

🔹 Source : 🔍 Observé dans pronote_sync/errors.py + pronote_sync/sources/pronote/client.py (lignes 346364).

Incompatibilités

  • Mode dry-run : Incompatible avec PRONOTE_AUTH_MODE=qr_token (risque de désynchronisation du token local).
    • pronote-sync --dry-run refuse le mode qr_token avant toute connexion.

🔹 Source : 🔍 docs/exploitation.md (ligne 6566).


Annexe A : Bibliothèques tierces

Bibliothèque Langage Dépôt Méthodes supportées Statut dans pronote-sync
pronotepy Python bain3/pronotepy Connexion directe, QR code/token, 30 ENT (liste fermée) Dépendance principale (version 2.15.7 vérifiée).
pronote-api TypeScript Litarvan/pronote-api Connexion directe, CAS, ENT Non utilisée.
pronote-qrcode-api JavaScript Androz2091/pronote-qrcode-api Déchiffrement QR code Non utilisée (intégration native via pronotepy).

🔹 Source : 🔍 Observé dans pyproject.toml (dépendances) + code source local (2026-09-12).


Annexe B : Tableau comparatif synthétique

Méthode Périmètre Identifiants Expiration Complexité Statut dans pronote-sync
URL iCal sécurisée EDT + devoirs (si inclus dans le flux) Jeton URL Longue durée (dépend de l'instance) Très faible Pris en charge
Connexion directe (mot de passe + ENT) Agenda/EDT, devoirs, messages Identifiant + mot de passe + ENT Session dépendante de l'instance Élevée Pris en charge
QR Code + token mobile Agenda/EDT, devoirs, messages PIN 4 chiffres → token + UUID QR ~10 min (⚠️ hypothèse) ; token dépendant de l'instance Modérée Pris en charge
SSO ENT (CAS/SAML) Identifiants ENT Session ENT Très élevée Non implémenté (seuls les 30 ENT de la liste fermée _ENT_NAMES sont supportés via pronotepy)
EduConnect Identifiants nationaux Session EduConnect Très élevée Non implémenté
CAS direct Identifiants CAS Ticket single-use Modérée Non implémenté
API publique N/A N/A N/A N/A Inexistante

Légende :

  • Périmètre : Les méthodes iCal sont en lecture seule (EDT + devoirs si inclus dans le flux). Les méthodes Connexion directe et QR Code + token mobile permettent les opérations pronotepy effectivement implémentées par ce projet (agenda, devoirs, messages ; informations ignorées en mode qr_token).
  • QR ~10 min : ⚠️ Hypothèse non vérifiée (observé dans pronotepy via un message d'exception, dépend de l'instance).
  • Session dépendante de l'instance : ⚠️ Hypothèse non vérifiée (nécessite un essai réel).

Annexe C : Écarts et notes de cohérence

Alignement avec .env.example

Paramètre Document Code Statut
PRONOTE_ICAL_URL Lignes 2, 4250 sources/ical.py Cohérent
PRONOTE_URL Ligne 3 client.py (ligne 294) Cohérent
PRONOTE_ENT Ligne 7 client.py (ligne 297, _ENT_NAMES) Cohérent
PRONOTE_AUTH_MODE=qr_token Ligne 23 client.py (ligne 334) Cohérent
PRONOTE_QR_CODE_FILE Ligne 24 client.py (ligne 387) Cohérent
PRONOTE_QR_PIN Ligne 25 client.py (ligne 388) Cohérent
« Le QR code se génère sur le site web » Ligne 21 Section Procédure QR Cohérent

Écarts avec docs/exploitation.md

Élément exploitation.md Ce document Action
« Le QR code expire ~10 minutes » Ligne 22 ⚠️ Hypothèse non vérifiée (section Cycle de vie) Aucune (hors périmètre).
« Mode qr_token incompatible avec dry-run » Lignes 6566 Section Incompatibilités Cohérent
« Fichier .pronote_auth_state.json (mode 0600) » Lignes 7075 Section Sécurité Cohérent

Glossaire

Terme Définition
ENT Espace Numérique de Travail (ex. Mon Bureau Numérique, Paris Classe Numérique).
Jeton icalsecurise Token secret intégré dans l'URL iCal, équivalent à un mot de passe.
jetonConnexionAppliMobile Token obtenu après appairage QR code, dont la durée dépend de l'instance/du serveur et n'est pas garantie.
UUID Identifiant unique permanent pour l'application (ex. pronote-sync-{uuid4()}).
PIN Code à 4 chiffres défini lors de la génération du QR code.

Historique des révisions

Date Auteur Modifications
2026-09-12 Agent tech-writer Refonte complète : qualification des affirmations, ajout des sources, tableau de compatibilité, procédure QR alignée sur pronotepy 2.15.7.
2026-09-12 Agent tech-writer Corrections suite à revue indépendante (ticket #10) : précision cryptographie (AES-128), qualification des sources, alignement nombre d'ENT (30), clarification SSO/CAS, exemples non copiables, note d'essai réel.
2026-09-12 Agent tech-writer Corrections suite à revue ticket #10 : suppression de tous les placeholders de secrets remplacés par de la prose descriptive ; clarification du périmètre réel des méthodes d'authentification (accès limité aux opérations implémentées) ; qualification de la durée du token jetonConnexionAppliMobile comme dépendante de l'instance/serveur et non garantie.