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).
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% ANNEXE B : TABLEAU COMPARATIF SYNTHÉTIQUE
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Tableau comparatif synthétique}
|
||||||
|
\label{annex:comparison}
|
||||||
|
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{Comparatif des méthodes d'authentification}
|
||||||
|
\label{tab:comparison}
|
||||||
|
\begin{tabularx}{\textwidth}{L{2cm} L{2.5cm} L{2.5cm} L{2cm} L{2cm} L{2.5cm}}
|
||||||
|
\toprule
|
||||||
|
\textbf{Méthode} & \textbf{Périmètre} & \textbf{Identifiants} & \textbf{Expiration} & \textbf{Complexité} & \textbf{Statut dans \texttt{pronote-sync}} \\
|
||||||
|
\midrule
|
||||||
|
|
||||||
|
\textbf{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 & \emojicheck\ Pris en charge \\
|
||||||
|
|
||||||
|
\textbf{Connexion directe} (mot de passe + ENT) & Agenda/EDT, devoirs, messages & Identifiant + mot de passe + ENT & Session dépendante de l'instance & Élevée & \emojicheck\ Pris en charge \\
|
||||||
|
|
||||||
|
\textbf{QR Code + token mobile} & Agenda/EDT, devoirs, messages & PIN 4 chiffres \rightarrow token + UUID & QR ~10 min ({\warningicon\ hypothèse}) ; token dépendant de l'instance & Modérée & \emojicheck\ Pris en charge \\
|
||||||
|
|
||||||
|
\textbf{SSO ENT (CAS/SAML)} & — & Identifiants ENT & Session ENT & Très élevée & \emojicross\ Non implémenté (seuls les 30 ENT de la liste fermée \texttt{\_ENT\_NAMES} sont supportés via \texttt{pronotepy}) \\
|
||||||
|
|
||||||
|
\textbf{EduConnect} & — & Identifiants nationaux & Session EduConnect & Très élevée & \emojicross\ Non implémenté \\
|
||||||
|
|
||||||
|
\textbf{CAS direct} & — & Identifiants CAS & Ticket single-use & Modérée & \emojicross\ Non implémenté \\
|
||||||
|
|
||||||
|
\textbf{API publique} & N/A & N/A & N/A & N/A & \emojicross\ Inexistante \\
|
||||||
|
|
||||||
|
\bottomrule
|
||||||
|
\end{tabularx}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
\section*{Légende}
|
||||||
|
\addcontentsline{toc}{section}{Légende}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Périmètre} : Les méthodes \textbf{iCal} sont en lecture seule (EDT + devoirs si inclus
|
||||||
|
dans le flux). Les méthodes \textbf{Connexion directe} et \textbf{QR Code + token mobile}
|
||||||
|
permettent les opérations \texttt{pronotepy} effectivement implémentées par ce projet (agenda,
|
||||||
|
devoirs, messages ; informations ignorées en mode \texttt{qr\_token}).
|
||||||
|
\item \textbf{QR ~10 min} : {\warningicon\ \textbf{Hypothèse non vérifiée}} (observé dans
|
||||||
|
\texttt{pronotepy} via un message d'exception, dépend de l'instance).
|
||||||
|
\item \textbf{Session dépendante de l'instance} : {\warningicon\ \textbf{Hypothèse non vérifiée}}
|
||||||
|
(nécessite un essai réel).
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DE L'ANNEXE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% ANNEXE C : ÉCARTS ET NOTES DE COHÉRENCE
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Écarts et notes de cohérence}
|
||||||
|
\label{annex:ecarts}
|
||||||
|
|
||||||
|
\section{Alignement avec \texttt{.env.example}}
|
||||||
|
\label{sec:alignement-env}
|
||||||
|
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{Alignement avec \texttt{.env.example}}
|
||||||
|
\label{tab:alignement-env}
|
||||||
|
\begin{tabularx}{\textwidth}{L{4.2cm} L{3.2cm} L{4.4cm} L{2.2cm}}
|
||||||
|
\toprule
|
||||||
|
\textbf{Paramètre} & \textbf{Document} & \textbf{Code} & \textbf{Statut} \\
|
||||||
|
\midrule
|
||||||
|
|
||||||
|
\texttt{PRONOTE\_ICAL\_URL} & \emojicheck\ Lignes 2, 42--50 & \emojicheck\ \texttt{sources/ical.py} & \textbf{Cohérent} \\
|
||||||
|
|
||||||
|
\texttt{PRONOTE\_URL} & \emojicheck\ Ligne 3 & \emojicheck\ \texttt{client.py} (ligne 294) & \textbf{Cohérent} \\
|
||||||
|
|
||||||
|
\texttt{PRONOTE\_ENT} & \emojicheck\ Ligne 7 & \emojicheck\ \texttt{client.py} (ligne 297, \texttt{\_ENT\_NAMES}) & \textbf{Cohérent} \\
|
||||||
|
|
||||||
|
\texttt{PRONOTE\_AUTH\_MODE=qr\_token} & \emojicheck\ Ligne 23 & \emojicheck\ \texttt{client.py} (ligne 334) & \textbf{Cohérent} \\
|
||||||
|
|
||||||
|
\texttt{PRONOTE\_QR\_CODE\_FILE} & \emojicheck\ Ligne 24 & \emojicheck\ \texttt{client.py} (ligne 387) & \textbf{Cohérent} \\
|
||||||
|
|
||||||
|
\texttt{PRONOTE\_QR\_PIN} & \emojicheck\ Ligne 25 & \emojicheck\ \texttt{client.py} (ligne 388) & \textbf{Cohérent} \\
|
||||||
|
|
||||||
|
\emph{« Le QR code se génère sur le site web »} & \emojicheck\ Ligne 21 & \emojicheck\ Section « Procédure QR pour \texttt{pronote-sync} » & \textbf{Cohérent} \\
|
||||||
|
|
||||||
|
\bottomrule
|
||||||
|
\end{tabularx}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
\section{Écarts avec \texttt{docs/exploitation.md}}
|
||||||
|
\label{sec:ecarts-exploitation}
|
||||||
|
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{Écarts avec \texttt{docs/exploitation.md}}
|
||||||
|
\label{tab:ecarts-exploitation}
|
||||||
|
\begin{tabularx}{\textwidth}{L{4.2cm} L{2.6cm} L{5cm} L{2.6cm}}
|
||||||
|
\toprule
|
||||||
|
\textbf{Élément} & \textbf{\texttt{exploitation.md}} & \textbf{Ce document} & \textbf{Action} \\
|
||||||
|
\midrule
|
||||||
|
|
||||||
|
\emph{« Le QR code expire \textasciitilde{}10 minutes »} & Ligne 22 & \warningicon\ \textbf{Hypothèse non vérifiée} (section « Cycle de vie des tokens ») & \textbf{Aucune} (hors périmètre). \\
|
||||||
|
|
||||||
|
\emph{« Mode \texttt{qr\_token} incompatible avec dry-run »} & Lignes 65--66 & \emojicheck\ Section « Incompatibilités » & \textbf{Cohérent} \\
|
||||||
|
|
||||||
|
\emph{« Fichier \texttt{.pronote\_auth\_state.json} (mode 0600) »} & Lignes 70--75 & \emojicheck\ Section « Sécurité » & \textbf{Cohérent} \\
|
||||||
|
|
||||||
|
\bottomrule
|
||||||
|
\end{tabularx}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DE L'ANNEXE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% ANNEXE A : BIBLIOTHÈQUES TIERCES
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Bibliothèques tierces}
|
||||||
|
\label{annex:libraries}
|
||||||
|
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{Bibliothèques tierces et leur statut dans \texttt{pronote-sync}}
|
||||||
|
\label{tab:libraries}
|
||||||
|
\begin{tabularx}{\textwidth}{L{2.5cm} L{1.5cm} L{3cm} L{3cm} L{2.5cm}}
|
||||||
|
\toprule
|
||||||
|
\textbf{Bibliothèque} & \textbf{Langage} & \textbf{Dépôt} & \textbf{Méthodes supportées} & \textbf{Statut dans \texttt{pronote-sync}} \\
|
||||||
|
\midrule
|
||||||
|
|
||||||
|
\textbf{pronotepy} & Python & \url{https://github.com/bain3/pronotepy} & Connexion directe, QR code/token, \textbf{30 ENT} (liste fermée) & \emojicheck\ \textbf{Dépendance principale} (version \textbf{2.15.7} vérifiée). \\
|
||||||
|
|
||||||
|
\textbf{pronote-api} & TypeScript & \url{https://github.com/Litarvan/pronote-api} & Connexion directe, CAS, ENT & \emojicross\ Non utilisée. \\
|
||||||
|
|
||||||
|
\textbf{pronote-qrcode-api} & JavaScript & \url{https://github.com/Androz2091/pronote-qrcode-api} & Déchiffrement QR code & \emojicross\ Non utilisée (intégration native via \texttt{pronotepy}). \\
|
||||||
|
|
||||||
|
\bottomrule
|
||||||
|
\end{tabularx}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Source} : {\emojiinfo\ Observé dans \texttt{pyproject.toml}} (dépendances) + code source local
|
||||||
|
(2026-09-12).
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DE L'ANNEXE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% CHAPITRE : INTRODUCTION
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Introduction}
|
||||||
|
\label{ch:introduction}
|
||||||
|
|
||||||
|
Ce document documente \textbf{uniquement les méthodes d'authentification prises en charge ou
|
||||||
|
délégables par \texttt{pronote-sync}}, en alignement strict avec :
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Le code source de \texttt{pronote\_sync/sources/pronote/client.py} (liste fermée
|
||||||
|
\texttt{\_ENT\_NAMES}, gestion des tokens).
|
||||||
|
\item La bibliothèque \texttt{pronotepy} \textbf{2.15.7} (contrat des méthodes
|
||||||
|
\texttt{qrcode\_login}, \texttt{token\_login}, \texttt{export\_credentials}).
|
||||||
|
\item Les paramètres de configuration \texttt{.env.example} (lignes 21–25).
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\section{Périmètre}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item {\emojicheck\ \textbf{Pris en charge}} : Méthodes implémentées et testées dans
|
||||||
|
\texttt{pronote-sync}.
|
||||||
|
\item {\emojiinfo\ \textbf{Délégable à pronotepy}} : Méthodes gérées par \texttt{pronotepy}
|
||||||
|
mais non directement exposées par \texttt{pronote-sync}.
|
||||||
|
\item {\emojicross\ \textbf{Non implémenté}} : Méthodes non supportées (ex. CAS/SAML
|
||||||
|
générique, EduConnect direct).
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\section{Public cible}
|
||||||
|
|
||||||
|
Développeurs et intégrateurs de \texttt{pronote-sync}.
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU CHAPITRE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% CHAPITRE : MÉTHODE 1 — URL ICAL SÉCURISÉE
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Méthode 1 : URL iCal sécurisée (\texttt{icalsecurise})}
|
||||||
|
\label{ch:method1}
|
||||||
|
|
||||||
|
\section{Principe général}
|
||||||
|
|
||||||
|
Pronote expose un flux de calendrier en lecture seule conforme à la norme
|
||||||
|
\textbf{iCalendar (RFC 5545)}. L'accès est contrôlé par un \textbf{jeton secret} intégré dans
|
||||||
|
l'URL sous forme de paramètre de requête \texttt{icalsecurise}.
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Statut} : {\emojiinfo\ Observé localement} (fonctionnalité native de Pronote, version non spécifiée).
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
\section{Obtention du jeton}
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Se connecter à Pronote (Espace Parents ou Élève) via n'importe quelle méthode.
|
||||||
|
\item Accéder à la vue \guillemotleft Emploi du temps \guillemotright.
|
||||||
|
\item Utiliser la fonction \guillemotleft Export iCal \guillemotright ou \guillemotleft Exporter \guillemotright.
|
||||||
|
\item Pronote génère une URL contenant un jeton secret \texttt{icalsecurise}.
|
||||||
|
\item \textbf{Copier cette URL} : elle constitue une crédentiale unique sensible qui doit être
|
||||||
|
protégée comme un mot de passe.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Source} : {\emojiinfo\ Observé localement dans les interfaces Pronote} (version non spécifiée,
|
||||||
|
hypothèse à valider).
|
||||||
|
|
||||||
|
\textbf{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.
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
\section{Format de l'URL}
|
||||||
|
|
||||||
|
\begin{lstlisting}[language=bash, caption=Format d'URL iCal Pronote, label=lst:ical-url]
|
||||||
|
https://{etablissement}.index-education.net/pronote/ical/Edt_{prenom}.ics?icalsecurise={jeton}&version={version}¶m={param}
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{icalsecurise} : \textbf{Jeton secret} (crédentiale).
|
||||||
|
\item \texttt{version} : Version de Pronote (ex. \texttt{2024}).
|
||||||
|
\item \texttt{param} : Paramètres optionnels.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Source} : {\emojiinfo\ Analysé via \texttt{pronote\_sync/sources/ical.py}}.
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
\section{Cycle de vie}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Pérennité} : Le jeton reste valide jusqu'à :
|
||||||
|
\begin{itemize}
|
||||||
|
\item Révocation manuelle par l'utilisateur dans Pronote.
|
||||||
|
\item Régénération par l'établissement (ex. à la rentrée scolaire).
|
||||||
|
\end{itemize}
|
||||||
|
\item {\warningicon\ \textbf{Hypothèse à valider}} : La durée exacte dépend des politiques
|
||||||
|
de l'établissement (non documentée officiellement).
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Source} : {\warningicon\ Comportement variable selon les instances} (à tester localement).
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
\section{Sécurité}
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item \textbf{Surface d'attaque} : Le jeton est encodé dans l'URL \rightarrow risque d'exposition via :
|
||||||
|
\begin{itemize}
|
||||||
|
\item Logs serveur/proxy.
|
||||||
|
\item En-tête \texttt{Referer}.
|
||||||
|
\item Historique du navigateur.
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Recommandations} :
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Ne jamais versionner} l'URL (ex. dans \texttt{.env} ou Git).
|
||||||
|
\item Utiliser \textbf{HTTPS} (obligatoire).
|
||||||
|
\item Masquer l'URL dans les logs (ex. via \texttt{redact\_url()} dans
|
||||||
|
\texttt{pronote-sync}).
|
||||||
|
\end{itemize}
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Source} : {\warningicon\ Recommandation du projet} (inspirée des bonnes pratiques générales
|
||||||
|
de sécurité).
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
\section{Intégration dans \texttt{pronote-sync}}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Paramètre} : \texttt{PRONOTE\_ICAL\_URL} (ex. \texttt{.env.example} ligne 2).
|
||||||
|
\item \textbf{Comportement} :
|
||||||
|
\begin{itemize}
|
||||||
|
\item Prioritaire en mode \texttt{PRONOTE\_AGENDA\_SOURCE=auto}.
|
||||||
|
\item Si l'URL est invalide ou expire, repli automatique vers \texttt{pronotepy} (si
|
||||||
|
\texttt{PRONOTE\_AGENDA\_SOURCE=auto}).
|
||||||
|
\item \textbf{Aucun repli} si \texttt{PRONOTE\_AGENDA\_SOURCE=ical} (échec explicite).
|
||||||
|
\end{itemize}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Source} : {\emojiinfo\ \texttt{pronote\_sync/config/settings.py} +
|
||||||
|
\texttt{pronote\_sync/sources/ical.py}}.
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU CHAPITRE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% CHAPITRE : MÉTHODE 2 — CONNEXION DIRECTE
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Méthode 2 : Connexion directe (identifiant / mot de passe + ENT)}
|
||||||
|
\label{ch:method2}
|
||||||
|
|
||||||
|
\section{Principe général}
|
||||||
|
|
||||||
|
Connexion via le protocole propriétaire de Pronote (JSON sur HTTPS), avec
|
||||||
|
\textbf{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.
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Statut} : {\emojiinfo\ Observé dans le code local} (délégable à pronotepy via
|
||||||
|
\texttt{ParentClient} ou \texttt{Client}).
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
\section{Flux d'authentification}
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item \textbf{Initialisation} : Requête GET vers \texttt{/pronote/\{espace\}.html} (ex.
|
||||||
|
\texttt{parent.html}).
|
||||||
|
\begin{itemize}
|
||||||
|
\item Récupère \texttt{h} (ID de session), \texttt{a} (ID espace), \texttt{sCrA}/\texttt{sCoA}
|
||||||
|
(drapeaux chiffrement/compression).
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Échange de clés} : Requête POST vers
|
||||||
|
\texttt{/pronote/appelfonction/\{a\}/\{h\}/\{numeroOrdre\}}.
|
||||||
|
\item \textbf{Identification} : Soumission de \texttt{identifiant},
|
||||||
|
\texttt{genreConnexion=0}, \texttt{genreEspace=\{a\}}.
|
||||||
|
\item \textbf{Résolution du défi} :
|
||||||
|
\begin{itemize}
|
||||||
|
\item Calcul de \texttt{mtp = MAJUSCULE(HEX(SHA256(alea + mot\_de\_passe)))}.
|
||||||
|
\item Dérivation de \texttt{key\_challenge = MD5(nom\_utilisateur + mtp)}.
|
||||||
|
\item Déchiffrement du \texttt{challenge} avec
|
||||||
|
\textbf{AES-CBC utilisant une clé dérivée par MD5 (16 octets, soit AES-128)}.
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Authentification} : Soumission de la réponse au défi.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Source} : {\emojiinfo\ Observé dans le code local de \texttt{pronotepy} 2.15.7} (module
|
||||||
|
\texttt{clients.py} et \texttt{pronoteAPI.py}, vérifié le 2026-09-12).
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
\section{Intégration dans \texttt{pronote-sync}}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Paramètres} :
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{PRONOTE\_URL} (ex. \texttt{.env.example} ligne 3).
|
||||||
|
\item \texttt{PRONOTE\_USERNAME}, \texttt{PRONOTE\_PASSWORD}.
|
||||||
|
\item \texttt{PRONOTE\_ENT} (slug dans \texttt{\_ENT\_NAMES}).
|
||||||
|
\item \texttt{PRONOTE\_ACCOUNT\_TYPE} (ex. \texttt{parent}).
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Comportement} :
|
||||||
|
\begin{itemize}
|
||||||
|
\item Utilise \texttt{pronotepy.ParentClient} pour les comptes parents.
|
||||||
|
\item \textbf{Repli} : Si iCal échoue en mode \texttt{auto}, \texttt{pronotepy} est utilisé.
|
||||||
|
\item \textbf{Pas de repli} si \texttt{PRONOTE\_AGENDA\_SOURCE=pronotepy} (échec explicite).
|
||||||
|
\end{itemize}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Source} : {\emojiinfo\ \texttt{pronote\_sync/sources/pronote/client.py}} (méthode
|
||||||
|
\texttt{\_connect\_password}).
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
\section{ENT supportés}
|
||||||
|
|
||||||
|
Liste \textbf{fermée} des \textbf{30 ENT} résolubles (lignes 52–83 de
|
||||||
|
\texttt{pronote\_sync/sources/pronote/client.py}) :
|
||||||
|
|
||||||
|
\begin{lstlisting}[language=Python, caption=Liste des ENT supportés, label=lst:ent-list]
|
||||||
|
_monbureaunumerique, ent_elyco, bordeaux, ent_creuse, occitanie_montpellier, ...
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\begin{warningbox}
|
||||||
|
\textbf{Hypothèse à valider} : Les ENT non listés nécessitent une contribution à
|
||||||
|
\texttt{pronotepy}.
|
||||||
|
\end{warningbox}
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Source} : {\emojiinfo\ Code source local de \texttt{pronote-sync}} (2026-09-12).
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU CHAPITRE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% 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 21–25) 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 181–189) + \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:382–387}).
|
||||||
|
\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 245–280) + \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:382–387}).
|
||||||
|
\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 346–364).
|
||||||
|
\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 65–66).
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU CHAPITRE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% CHAPITRE : MÉTHODE 4 — SSO ENT (CAS/SAML)
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Méthode 4 : SSO ENT (CAS/SAML)}
|
||||||
|
\label{ch:method4}
|
||||||
|
|
||||||
|
\begin{warningbox}
|
||||||
|
\textbf{Statut} : {\emojicross\ Non implémenté} dans \texttt{pronote-sync}.
|
||||||
|
|
||||||
|
Seuls les 30 ENT de la liste fermée \texttt{\_ENT\_NAMES} (pronotepy 2.15.7) sont supportés via
|
||||||
|
\texttt{ent} dans \texttt{ParentClient}. \textbf{Pas de SSO générique CAS/SAML.}
|
||||||
|
\end{warningbox}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU CHAPITRE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% CHAPITRE : MÉTHODE 5 — EDUCONNECT (HUBEDUCONNECT)
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Méthode 5 : EduConnect (HubEduConnect)}
|
||||||
|
\label{ch:method5}
|
||||||
|
|
||||||
|
\begin{warningbox}
|
||||||
|
\textbf{Statut} : {\emojicross\ Non implémenté} dans \texttt{pronote-sync}.
|
||||||
|
|
||||||
|
Nécessite une intégration CAS/SAML générique, \textbf{non supportée par ce projet}.
|
||||||
|
\end{warningbox}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU CHAPITRE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% CHAPITRE : MÉTHODE 6 — CAS DIRECT
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Méthode 6 : CAS direct}
|
||||||
|
\label{ch:method6}
|
||||||
|
|
||||||
|
\begin{warningbox}
|
||||||
|
\textbf{Statut} : {\emojicross\ Non implémenté} dans \texttt{pronote-sync}.
|
||||||
|
|
||||||
|
Non supporté.
|
||||||
|
\end{warningbox}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU CHAPITRE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% CHAPITRE : MÉTHODE 7 — API PUBLIQUE
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Méthode 7 : API publique}
|
||||||
|
\label{ch:method7}
|
||||||
|
|
||||||
|
\begin{warningbox}
|
||||||
|
\textbf{Statut} : {\emojicross\ 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.
|
||||||
|
\end{warningbox}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU CHAPITRE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% CHAPITRE : TABLEAU DE COMPATIBILITÉ
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter{Tableau de compatibilité avec \texttt{pronote-sync}}
|
||||||
|
\label{ch:overview}
|
||||||
|
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{Méthodes d'authentification et leur statut dans \texttt{pronote-sync}}
|
||||||
|
\label{tab:compatibilite}
|
||||||
|
\begin{tabularx}{\textwidth}{L{2.5cm} L{3cm} L{3cm} L{2.5cm} L{4cm}}
|
||||||
|
\toprule
|
||||||
|
\textbf{Méthode} & \textbf{Statut dans \texttt{pronote-sync}} & \textbf{Implémentation} & \textbf{Source} & \textbf{Notes} \\
|
||||||
|
\midrule
|
||||||
|
|
||||||
|
|
||||||
|
\textbf{URL iCal sécurisée} (\texttt{icalsecurise}) & \emojicheck\ Pris en charge & Source \texttt{ical} (prioritaire en mode \texttt{auto}) & \emojiinfo\ \texttt{pronote\_sync/sources/ical.py} & Jeton dans l'URL traité comme secret. \\
|
||||||
|
|
||||||
|
\textbf{Connexion directe} (mot de passe + ENT) & \emojicheck\ Pris en charge & Source \texttt{pronotepy} (repli si iCal échoue) & \emojiinfo\ \texttt{pronote\_sync/sources/pronote/client.py} & Liste fermée \texttt{\_ENT\_NAMES} (lignes 52–84). \\
|
||||||
|
|
||||||
|
\textbf{QR Code + token mobile} & \emojicheck\ Pris en charge & Mode \texttt{PRONOTE\_AUTH\_MODE=qr\_token} & \emojiinfo\ \texttt{pronotepy.Client.qrcode\_login} + \texttt{token\_login} & Voir \hyperref[sec:procedure-qr]{Procédure QR} (Section \ref{sec:procedure-qr}). \\
|
||||||
|
|
||||||
|
\textbf{SSO ENT (CAS/SAML)} & \emojicross\ Non implémenté & — & — & Seuls les 30 ENT de la liste fermée \texttt{\_ENT\_NAMES} (pronotepy 2.15.7) sont supportés via \texttt{ent} dans \texttt{ParentClient}. \textbf{Pas de SSO générique CAS/SAML.} \\
|
||||||
|
|
||||||
|
\textbf{EduConnect (HubEduConnect)} & \emojicross\ Non implémenté & — & — & Nécessite une intégration CAS/SAML générique, \textbf{non supportée par ce projet}. \\
|
||||||
|
|
||||||
|
\textbf{CAS direct} & \emojicross\ Non implémenté & — & — & Non supporté. \\
|
||||||
|
|
||||||
|
\textbf{API publique} & \emojicross\ 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. \\
|
||||||
|
|
||||||
|
\bottomrule
|
||||||
|
\end{tabularx}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU CHAPITRE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% PAGE DE TITRE — Authentification Pronote
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\begin{titlepage}
|
||||||
|
\newgeometry{margin=2cm}
|
||||||
|
\begin{center}
|
||||||
|
\vspace*{2cm}
|
||||||
|
|
||||||
|
{\Huge\bfseries\color{primaryNavy} Authentification Pronote\\}
|
||||||
|
{\huge\bfseries\color{secondarySlate} Référence technique pour \texttt{pronote-sync}}
|
||||||
|
|
||||||
|
\vspace{1.5cm}
|
||||||
|
|
||||||
|
{\Large\color{secondarySlate} Version 1.0 — 12 septembre 2026}
|
||||||
|
|
||||||
|
\vspace{2cm}
|
||||||
|
|
||||||
|
{\large\color{gray} Équipe Architecture et Sécurité}
|
||||||
|
|
||||||
|
\vspace{1cm}
|
||||||
|
|
||||||
|
{\small\color{gray}
|
||||||
|
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).
|
||||||
|
}
|
||||||
|
|
||||||
|
\vspace{2cm}
|
||||||
|
|
||||||
|
\begin{warningbox}
|
||||||
|
\centering
|
||||||
|
{\bfseries\large\color{warningRed} AVERTISSEMENT}\\
|
||||||
|
\vspace{0.5cm}
|
||||||
|
{\small
|
||||||
|
Ce document repose sur des observations directes du code source de
|
||||||
|
\texttt{pronotepy} (version 2.15.7, vérifiée localement le 2026-09-12), des issues
|
||||||
|
publiques du dépôt \texttt{bain3/pronotepy}, et des tests d'intégration du projet
|
||||||
|
\texttt{pronote-sync}.\\
|
||||||
|
|
||||||
|
{\bfseries 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.}
|
||||||
|
}
|
||||||
|
\end{warningbox}
|
||||||
|
|
||||||
|
\vfill
|
||||||
|
|
||||||
|
{\small\color{gray} Compilé avec LuaLaTeX}
|
||||||
|
|
||||||
|
\end{center}
|
||||||
|
\restoregeometry
|
||||||
|
\end{titlepage}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% TABLE DES MATIÈRES
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
\tableofcontents
|
||||||
|
\thispagestyle{fancy}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% LISTE DES TABLEAUX (optionnel)
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
\listoftables
|
||||||
|
\thispagestyle{fancy}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% AVERTISSEMENT INITIAL
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
\section*{Avertissement initial}
|
||||||
|
\addcontentsline{toc}{section}{Avertissement initial}
|
||||||
|
|
||||||
|
\begin{infobox}
|
||||||
|
\textbf{Convention de qualification} :
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item {\emojiinfo\ \textbf{Observé dans le code local}} : Mécanisme vérifié dans le code
|
||||||
|
source de \texttt{pronotepy} 2.15.7 ou \texttt{pronote-sync}.
|
||||||
|
\item {\emojiinfo\ \textbf{Observé localement}} : Comportement constaté dans les interfaces
|
||||||
|
Pronote (version non spécifiée, hypothèse à valider).
|
||||||
|
\item {\warningicon\ \textbf{Hypothèse à valider}} : Affirmation non vérifiée, nécessitant
|
||||||
|
une confirmation par test sur une instance réelle.
|
||||||
|
\end{itemize}
|
||||||
|
\end{infobox}
|
||||||
|
|
||||||
|
\vspace{1cm}
|
||||||
|
|
||||||
|
\begin{warningbox}
|
||||||
|
\textbf{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.
|
||||||
|
\end{warningbox}
|
||||||
|
|
||||||
|
\newpage
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% GLOSSAIRE (chapitre non numéroté)
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter*{Glossaire}
|
||||||
|
\addcontentsline{toc}{chapter}{Glossaire}
|
||||||
|
|
||||||
|
\begin{tabularx}{\textwidth}{L{4cm} L{12cm}}
|
||||||
|
\toprule
|
||||||
|
\textbf{Terme} & \textbf{Définition} \\
|
||||||
|
\midrule
|
||||||
|
|
||||||
|
\textbf{ENT} & Espace Numérique de Travail (ex. Mon Bureau Numérique, Paris Classe Numérique). \\
|
||||||
|
|
||||||
|
\textbf{Jeton \texttt{icalsecurise}} & Token secret intégré dans l'URL iCal, équivalent à un mot de passe. \\
|
||||||
|
|
||||||
|
\textbf{\texttt{jetonConnexionAppliMobile}} & Token obtenu après appairage QR code, dont la durée dépend de l'instance/du serveur et n'est pas garantie. \\
|
||||||
|
|
||||||
|
\textbf{UUID} & Identifiant unique permanent pour l'application (ex. \texttt{pronote-sync-\{uuid4()\}}). \\
|
||||||
|
|
||||||
|
\textbf{PIN} & Code à 4 chiffres défini lors de la génération du QR code. \\
|
||||||
|
|
||||||
|
\bottomrule
|
||||||
|
\end{tabularx}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU GLOSSAIRE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% HISTORIQUE DES RÉVISIONS (chapitre non numéroté)
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
\chapter*{Historique des révisions}
|
||||||
|
\addcontentsline{toc}{chapter}{Historique des révisions}
|
||||||
|
|
||||||
|
\begin{tabularx}{\textwidth}{L{2.4cm} L{2.6cm} L{11cm}}
|
||||||
|
\toprule
|
||||||
|
\textbf{Date} & \textbf{Auteur} & \textbf{Modifications} \\
|
||||||
|
\midrule
|
||||||
|
|
||||||
|
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 \texttt{jetonConnexionAppliMobile} comme dépendante de l'instance/serveur et non garantie. \\
|
||||||
|
|
||||||
|
\bottomrule
|
||||||
|
\end{tabularx}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DE L'HISTORIQUE
|
||||||
|
% =============================================================================
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
% =============================================================================
|
||||||
|
% PRÉAMBULE LaTeX — Authentification Pronote
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
% --- Classe de document ---
|
||||||
|
\documentclass[11pt,a4paper,oneside]{report}
|
||||||
|
|
||||||
|
% --- Encodage et langue ---
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage[french]{babel}
|
||||||
|
\usepackage{lmodern}
|
||||||
|
|
||||||
|
% --- Polices (plan documentaire : EB Garamond / Carlito / DejaVu Sans Mono) ---
|
||||||
|
% EB Garamond (sérif) : police principale du document
|
||||||
|
\usepackage{ebgaramond}
|
||||||
|
% Carlito (sans-sérif, compatible métriquement Calibri)
|
||||||
|
\usepackage[sfdefault]{carlito}
|
||||||
|
% DejaVu Sans Mono (chasse fixe) : code, JSON, requêtes HTTP
|
||||||
|
% (fontspec est déjà chargé par EB Garamond sous LuaLaTeX)
|
||||||
|
\setmonofont{DejaVu Sans Mono}[Scale=0.9]
|
||||||
|
|
||||||
|
% --- Couleurs (palette Bleu Institutionnel & Ardoise) ---
|
||||||
|
\usepackage{xcolor}
|
||||||
|
\definecolor{primaryNavy}{RGB}{20,45,85}
|
||||||
|
\definecolor{secondarySlate}{RGB}{70,95,125}
|
||||||
|
\definecolor{accentSteel}{RGB}{0,115,150}
|
||||||
|
\definecolor{lightGray}{RGB}{240,240,240}
|
||||||
|
\definecolor{warningRed}{RGB}{180,50,50}
|
||||||
|
|
||||||
|
% --- Mise en page ---
|
||||||
|
\usepackage[a4paper, margin=2.5cm, top=2cm, bottom=2cm]{geometry}
|
||||||
|
\usepackage{parskip}
|
||||||
|
\setlength{\parskip}{1em}
|
||||||
|
\setlength{\parindent}{0pt}
|
||||||
|
|
||||||
|
% --- Hyperliens et PDF ---
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\hypersetup{
|
||||||
|
colorlinks=true,
|
||||||
|
linkcolor=accentSteel,
|
||||||
|
urlcolor=accentSteel,
|
||||||
|
citecolor=secondarySlate,
|
||||||
|
filecolor=primaryNavy,
|
||||||
|
menucolor=primaryNavy,
|
||||||
|
runcolor=primaryNavy,
|
||||||
|
pdfauthor={Équipe Architecture & Sécurité},
|
||||||
|
pdftitle={Authentification Pronote — Référence technique},
|
||||||
|
pdfsubject={Référence technique d'authentification pour pronote-sync},
|
||||||
|
pdfkeywords={Pronote, authentification, pronote-sync, QR code, token, ENT, iCal},
|
||||||
|
bookmarksopen=true,
|
||||||
|
bookmarksnumbered=true
|
||||||
|
}
|
||||||
|
|
||||||
|
% --- Titres et sections ---
|
||||||
|
\usepackage{titlesec}
|
||||||
|
\titleformat{\chapter}[display]
|
||||||
|
{\normalfont\huge\bfseries\color{primaryNavy}}
|
||||||
|
{\chaptertitlename\ \thechapter}
|
||||||
|
{20pt}
|
||||||
|
{\Huge\color{primaryNavy}}
|
||||||
|
\titleformat{\section}
|
||||||
|
{\normalfont\Large\bfseries\color{primaryNavy}}
|
||||||
|
{\thesection}
|
||||||
|
{1em}
|
||||||
|
{\color{primaryNavy}}
|
||||||
|
\titleformat{\subsection}
|
||||||
|
{\normalfont\large\bfseries\color{secondarySlate}}
|
||||||
|
{\thesubsection}
|
||||||
|
{1em}
|
||||||
|
{\color{secondarySlate}}
|
||||||
|
\titleformat{\subsubsection}
|
||||||
|
{\normalfont\bfseries\color{secondarySlate}}
|
||||||
|
{\thesubsubsection}
|
||||||
|
{1em}
|
||||||
|
{\color{secondarySlate}}
|
||||||
|
|
||||||
|
% --- Tableaux ---
|
||||||
|
\usepackage{tabularx}
|
||||||
|
\usepackage{booktabs}
|
||||||
|
\usepackage{array}
|
||||||
|
\newcolumntype{L}[1]{>{\raggedright\let\newline\\\arraybackslash\hspace{0pt}\hspace{1em}}p{#1}}
|
||||||
|
\newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}\hspace{1em}}p{#1}}
|
||||||
|
\newcolumntype{R}[1]{>{\raggedleft\let\newline\\\arraybackslash\hspace{0pt}\hspace{1em}}p{#1}}
|
||||||
|
|
||||||
|
% --- Listes et encadrés ---
|
||||||
|
\usepackage{enumitem}
|
||||||
|
\setlist[itemize]{leftmargin=*, topsep=0.5em, itemsep=0.25em}
|
||||||
|
\setlist[enumerate]{leftmargin=*, topsep=0.5em, itemsep=0.25em}
|
||||||
|
|
||||||
|
% --- Callouts (encadrés colorés) ---
|
||||||
|
\usepackage{mdframed}
|
||||||
|
\newmdenv[linecolor=warningRed, linewidth=2pt, leftmargin=10pt, rightmargin=10pt, innerleftmargin=10pt, innerrightmargin=10pt, backgroundcolor=red!5!white, roundcorner=5pt, skipabove=10pt, skipbelow=10pt]{warningbox}
|
||||||
|
\newmdenv[linecolor=secondarySlate, linewidth=2pt, leftmargin=10pt, rightmargin=10pt, innerleftmargin=10pt, innerrightmargin=10pt, backgroundcolor=blue!5!white, roundcorner=5pt, skipabove=10pt, skipbelow=10pt]{infobox}
|
||||||
|
|
||||||
|
% --- Code source ---
|
||||||
|
\usepackage{listings}
|
||||||
|
\lstdefinestyle{pronote}{
|
||||||
|
basicstyle=\ttfamily\footnotesize,
|
||||||
|
breaklines=true,
|
||||||
|
frame=single,
|
||||||
|
rulecolor=\color{gray!30},
|
||||||
|
backgroundcolor=\color{lightGray},
|
||||||
|
keywordstyle=\color{primaryNavy},
|
||||||
|
stringstyle=\color{secondarySlate},
|
||||||
|
commentstyle=\color{gray},
|
||||||
|
showstringspaces=false,
|
||||||
|
tabsize=2,
|
||||||
|
captionpos=b,
|
||||||
|
xleftmargin=10pt,
|
||||||
|
xrightmargin=10pt,
|
||||||
|
aboveskip=10pt,
|
||||||
|
belowskip=10pt
|
||||||
|
}
|
||||||
|
\lstset{style=pronote}
|
||||||
|
|
||||||
|
% --- Symboles et icônes ---
|
||||||
|
\usepackage{amssymb}
|
||||||
|
\usepackage{pifont}
|
||||||
|
\newcommand{\checkmarkicon}{\ding{51}} % ✓
|
||||||
|
\newcommand{\warningicon}{\ding{43}} % ⚠
|
||||||
|
\newcommand{\infoicon}{\ding{48}} % ℹ
|
||||||
|
\newcommand{\crossicon}{\ding{55}} % ✗
|
||||||
|
|
||||||
|
% --- Mathématiques ---
|
||||||
|
\usepackage{amsmath}
|
||||||
|
|
||||||
|
% --- Table des matières ---
|
||||||
|
\usepackage{tocloft}
|
||||||
|
\renewcommand{\cftchapfont}{\normalfont\bfseries\color{primaryNavy}}
|
||||||
|
\renewcommand{\cftsecfont}{\normalfont\color{primaryNavy}}
|
||||||
|
\renewcommand{\cftsubsecfont}{\normalfont\color{secondarySlate}}
|
||||||
|
|
||||||
|
% --- En-têtes et pieds de page ---
|
||||||
|
\usepackage{fancyhdr}
|
||||||
|
\pagestyle{fancy}
|
||||||
|
\fancyhf{}
|
||||||
|
\fancyhead[LE,RO]{\thepage}
|
||||||
|
\fancyhead[LO]{\nouppercase{\rightmark}}
|
||||||
|
\fancyhead[RE]{\nouppercase{\leftmark}}
|
||||||
|
\renewcommand{\headrulewidth}{0.5pt}
|
||||||
|
\renewcommand{\footrulewidth}{0pt}
|
||||||
|
|
||||||
|
% --- Espacement vertical ---
|
||||||
|
\usepackage{setspace}
|
||||||
|
\onehalfspacing
|
||||||
|
|
||||||
|
% --- Césure ---
|
||||||
|
\usepackage{microtype}
|
||||||
|
|
||||||
|
% --- Support des emojis (repli sur texte si non disponible) ---
|
||||||
|
\newcommand{\emojiwarning}{\warningicon}
|
||||||
|
\newcommand{\emojicheck}{\checkmarkicon}
|
||||||
|
\newcommand{\emojicross}{\crossicon}
|
||||||
|
\newcommand{\emojiinfo}{\infoicon}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
% FIN DU PRÉAMBULE
|
||||||
|
% =============================================================================
|
||||||
Binary file not shown.
@@ -9,8 +9,8 @@
|
|||||||
%%
|
%%
|
||||||
%% INSTRUCTIONS DE COMPILATION :
|
%% INSTRUCTIONS DE COMPILATION :
|
||||||
%% Ce document est conçu pour être compilé avec LuaLaTeX :
|
%% Ce document est conçu pour être compilé avec LuaLaTeX :
|
||||||
%% lualatex -interaction=nonstopmode docs/pronote-auth.tex
|
%% TEXINPUTS="docs:" lualatex -interaction=nonstopmode -output-directory=docs docs/pronote-auth.tex
|
||||||
%% lualatex -interaction=nonstopmode docs/pronote-auth.tex
|
%% TEXINPUTS="docs:" lualatex -interaction=nonstopmode -output-directory=docs docs/pronote-auth.tex
|
||||||
%% (Deux passes nécessaires pour la génération de la table des matières,
|
%% (Deux passes nécessaires pour la génération de la table des matières,
|
||||||
%% des références croisées et des hyperliens).
|
%% des références croisées et des hyperliens).
|
||||||
%%
|
%%
|
||||||
@@ -52,5 +52,9 @@
|
|||||||
|
|
||||||
\include{annex-libraries}
|
\include{annex-libraries}
|
||||||
\include{annex-comparison}
|
\include{annex-comparison}
|
||||||
|
\include{annex-ecarts}
|
||||||
|
|
||||||
|
\include{glossaire}
|
||||||
|
\include{historique}
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|||||||
Reference in New Issue
Block a user