Files
college-infos/docs/ch-method3.tex
T
OpenCode 423a32f220 docs(pronote-auth): reconstruire le source LaTeX et régénérer le PDF
Les fichiers de chapitres référencés par docs/pronote-auth.tex (preamble, frontmatter, ch-*, annex-*) n'avaient jamais été committés, rendant le PDF non reproductible. Reconstitution fidèle depuis docs/pronote-auth.md, correction des instructions de compilation (TEXINPUTS + -output-directory), ajout de l'Annexe C, du Glossaire et de l'Historique des révisions, PDF régénéré (27 pages).
2026-09-12 21:17:23 +02:00

213 lines
9.6 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
% =============================================================================
% CHAPITRE : MÉTHODE 3 — QR CODE + TOKEN MOBILE
% =============================================================================
\chapter{Méthode 3 : QR Code + token mobile (pour \texttt{pronote-sync})}
\label{ch:method3}
\section{Principe général}
Mécanisme d'appairage par QR code pour les appareils mobiles, \textbf{contournant
l'authentification ENT/EduConnect}. Le QR code est généré \textbf{depuis l'interface web
Pronote, espace parent \rightarrow paramètres \rightarrow QR code}, puis utilisé avec un
\textbf{PIN à 4 chiffres} pour obtenir un token dont la durée dépend de l'instance/serveur.
\begin{infobox}
\textbf{Statut} : {\emojicheck\ Pris en charge} par \texttt{pronote-sync} (mode
\texttt{PRONOTE\_AUTH\_MODE=qr\_token}).
\end{infobox}
\section{Procédure QR pour \texttt{pronote-sync}}
\label{sec:procedure-qr}
\subsection{Étape 1 : Génération du QR code (interface web)}
\begin{enumerate}
\item Se connecter à Pronote via un navigateur (espace \textbf{Parent}).
\item Aller dans \textbf{Paramètres \rightarrow Accès mobile / Application mobile}.
\item Définir un \textbf{PIN temporaire à 4 chiffres}.
\item Pronote affiche un \textbf{QR code} contenant un JSON avec les clés :
\begin{itemize}
\item \texttt{login}, \texttt{jeton}, et \texttt{url} (ex.
\texttt{https://[host]/pronote/mobile.parent.html}).
\end{itemize}
\textbf{Le fichier JSON réel contient des identifiants chiffrés et ne doit jamais être
copié, partagé, ou committé.}
\item \textbf{Exporter le QR code} :
\begin{itemize}
\item Sauvegardez le fichier JSON localement ou scannez-le avec un appareil.
\item \textbf{Ne jamais partager} le JSON ou le PIN.
\item \textbf{Le fichier JSON du QR code contient des identifiants chiffrés : ne jamais
le coller dans la documentation ni le committer.}
\end{itemize}
\end{enumerate}
\begin{infobox}
\textbf{Source} : {\emojiinfo\ Observé localement dans l'interface web Pronote} (version non
spécifiée, hypothèse à valider).
\end{infobox}
\subsection{Étape 2 : Configuration de \texttt{pronote-sync}}
\begin{enumerate}
\item \textbf{Enregistrer le QR code} :
\begin{itemize}
\item Sauvegarder le JSON dans un fichier (ex. \texttt{/path/to/qr\_code.json}).
\item \textbf{Permissions} : \texttt{chmod 600 /path/to/qr\_code.json}.
\end{itemize}
\item \textbf{Configurer \texttt{.env}} :
\begin{lstlisting}[language=bash, caption=Configuration QR Code dans .env, label=lst:qr-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)
\end{lstlisting}
\textbf{Note} : \texttt{.env.example} ne doit \textbf{jamais} contenir de PIN concret.
\end{enumerate}
\begin{infobox}
\textbf{Source} : {\emojiinfo\ Observé dans \texttt{.env.example}} (lignes 2125) et
\texttt{pronote\_sync/sources/pronote/client.py}.
\end{infobox}
\subsection{Étape 3 : Premier login (enrôlement)}
\begin{enumerate}
\item \texttt{pronote-sync} lit \texttt{PRONOTE\_QR\_CODE\_FILE} et \texttt{PRONOTE\_QR\_PIN}.
\item Appel à \texttt{pronotepy.ParentClient.qrcode\_login(qr\_code, pin, uuid)} :
\begin{itemize}
\item \texttt{qr\_code} : JSON du fichier QR.
\item \texttt{pin} : PIN à 4 chiffres.
\item \texttt{uuid} : UUID permanent généré par \texttt{pronote-sync} (ex.
\texttt{pronote-sync-\{uuid4()\}}).
\end{itemize}
\item \textbf{Déchiffrement} :
\begin{itemize}
\item Algorithme :
\textbf{AES-CBC utilisant une clé dérivée par MD5 (16 octets, soit AES-128)}.
\item Clé : \texttt{MD5(PIN)} (dérivée du PIN secret).
\item IV : 16 octets nuls.
\item Résultat : \texttt{login} et \texttt{jeton} en clair.
\end{itemize}
\item \textbf{Échange de token} : Pronote retourne un \texttt{jetonConnexionAppliMobile} (token
dont la durée dépend de l'instance/serveur).
\item \textbf{Persistance} : \texttt{pronote-sync} sauvegarde les credentials via
\texttt{export\_credentials()} dans \texttt{.pronote\_auth\_state.json} (mode \texttt{0600}).
\end{enumerate}
\begin{infobox}
\textbf{Source} : {\emojiinfo\ Observé dans le code local de \texttt{pronotepy} 2.15.7}
(\texttt{clients.py} lignes 181189) + \texttt{pronote\_sync/sources/pronote/client.py} (méthode
\texttt{\_enroll\_qr\_code}).
\end{infobox}
\subsection{Étape 4 : Connexions ultérieures (auto-login)}
\begin{enumerate}
\item \texttt{pronote-sync} charge \texttt{.pronote\_auth\_state.json}.
\item Appel à \texttt{pronotepy.ParentClient.token\_login(**credentials)} :
\begin{itemize}
\item \texttt{pronote\_url}, \texttt{username}, \texttt{password} (token), \texttt{uuid}.
\end{itemize}
\item \textbf{Rotation du token} : Le token est \textbf{remplacé uniquement si le serveur
renvoie \texttt{jetonConnexionAppliMobile}} (observé dans \texttt{pronotepy} 2.15.7,
\texttt{clients.py:382387}).
\item \textbf{Persistance} : Les credentials sont sauvegardés dans
\texttt{.pronote\_auth\_state.json} après chaque opération réussie.
\end{enumerate}
\begin{infobox}
\textbf{Source} : {\emojiinfo\ Observé dans le code local de \texttt{pronotepy} 2.15.7}
(\texttt{clients.py} lignes 245280) + \texttt{pronote\_sync/sources/pronote/client.py} (méthode
\texttt{\_connect\_qr\_token}).
\end{infobox}
\section{Cycle de vie des tokens}
\begin{itemize}
\item \textbf{QR code} : Valide \textbf{~10 minutes} après génération
({\warningicon\ \textbf{Hypothèse à valider}} : cette durée n'est attestée que par un
message d'exception dans \texttt{pronotepy} et n'est pas une garantie officielle/indépendante
de l'instance).
\item \textbf{\texttt{jetonConnexionAppliMobile}} :
\begin{itemize}
\item Durée \textbf{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).
\item \textbf{Remplacé uniquement si le serveur renvoie
\texttt{jetonConnexionAppliMobile}} (observé dans \texttt{pronotepy} 2.15.7,
\texttt{clients.py:382387}).
\item \textbf{Révocable} manuellement dans Pronote (Paramètres \rightarrow Accès mobile).
\end{itemize}
\end{itemize}
\begin{infobox}
\textbf{Source} : {\warningicon\ Comportement variable selon les instances} (à tester localement).
\end{infobox}
\section{Sécurité}
\begin{enumerate}
\item \textbf{Fichiers sensibles} :
\begin{itemize}
\item \texttt{.pronote\_auth\_state.json} : \textbf{Ne jamais versionner} (couvert par
\texttt{.gitignore}).
\item \texttt{PRONOTE\_QR\_CODE\_FILE} : \textbf{Ne jamais committer} (ex. dans Git).
\end{itemize}
\item \textbf{Secrets} :
\begin{itemize}
\item Le PIN et le contenu du QR code sont \textbf{masqués} dans les logs (via
\texttt{redact\_secrets()}).
\item Les exceptions sont \textbf{expurgées} (via \texttt{redact\_exception()}).
\end{itemize}
\item \textbf{Recommandations} :
\begin{itemize}
\item Utiliser un \textbf{PIN robuste} (éviter les codes simples comme \guillemotleft 0000 \guillemotright ou
des séquences évidentes).
\item \textbf{Révoquer} le token en cas de compromission (via Pronote web).
\end{itemize}
\end{enumerate}
\begin{infobox}
\textbf{Source} : {\emojiinfo\ \texttt{pronote\_sync/utils/redaction.py} +
\texttt{pronote\_sync/sources/pronote/client.py}} (méthode \texttt{\_collect\_auth\_secrets}).
\end{infobox}
\section{Erreurs et repli}
\begin{itemize}
\item \textbf{\texttt{PronoteAuthRotationError}} : Levée si :
\begin{itemize}
\item Le token persisté est \textbf{invalide/expiré}.
\item Le fichier QR ou le PIN est \textbf{manquant/invalide}.
\end{itemize}
\item \textbf{Action requise} :
\begin{enumerate}
\item Supprimer \texttt{.pronote\_auth\_state.json}.
\item Générer un \textbf{nouveau QR code depuis l'interface web Pronote, espace parent}.
\item Relancer \texttt{pronote-sync}.
\end{enumerate}
\end{itemize}
\begin{infobox}
\textbf{Source} : {\emojiinfo\ Observé dans \texttt{pronote\_sync/errors.py} +
\texttt{pronote\_sync/sources/pronote/client.py}} (lignes 346364).
\end{infobox}
\section{Incompatibilités}
\begin{itemize}
\item \textbf{Mode \texttt{dry-run}} : \textbf{Incompatible} avec
\texttt{PRONOTE\_AUTH\_MODE=qr\_token} (risque de désynchronisation du token local).
\begin{itemize}
\item \texttt{pronote-sync --dry-run} \textbf{refuse} le mode \texttt{qr\_token} avant toute
connexion.
\end{itemize}
\end{itemize}
\begin{infobox}
\textbf{Source} : {\emojiinfo\ \texttt{docs/exploitation.md}} (ligne 6566).
\end{infobox}
% =============================================================================
% FIN DU CHAPITRE
% =============================================================================