LTI authentifie l'élève et le fait rejoindre sa classe (même code que le code/QR existant), pas lancer un lab précis - relecture du CLAUDE.md qui liste LTI avec les autres façons d'ajouter des élèves. packbackbooks/lti-1p3-tool (Apache-2.0, recommandé par le CLAUDE.md), trois ponts vers Redis/cookies/MariaDB, élève retrouvé par identité Moodle stable pour ne jamais créer de doublon. Enregistrement d'une plateforme/d'un déploiement par commande Artisan (opération rare, faite à la main par Adam), jamais une page d'administration. Corrige au passage un vrai bug préexistant trouvé en vérifiant en réel sur le serveur : withoutMiddleware(ValidateCsrfToken::class) sur une route ne retire jamais le vrai middleware CSRF (ValidateCsrfToken est un alias déprécié de PreventRequestForgery, pas la classe réellement enregistrée) - /csp-rapport avait le même défaut depuis l'étape 14, invisible faute de surveillance. Corrigé pour les deux par la bonne méthode (validateCsrfTokens except, dans bootstrap/app.php). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
4 KiB
ADR 0010 — LTI 1.3 Moodle : une 6ᵉ façon de rejoindre une classe, pas un lancement de lab
- Date : 2026-10-14
- Statut : accepté
Contexte
CLAUDE.md, section 6 : « Moodle LTI 1.3 (V2) » est listé avec les autres façons d'ajouter des élèves (code/QR, import CSV, saisie rapide, invitation e-mail) — pas dans la description de l'espace de lab. Avancé à la demande explicite d'Adam (bloc C terminé, V2 lancée par anticipation).
Décisions
LTI sert à rejoindre une classe, pas à lancer un lab précis. Un
lancement Moodle authentifie l'élève (OIDC + jeton signé) et le fait
atterrir sur son tableau de bord habituel (eleve.show) — depuis là, il
choisit un lab ou un devoir normalement, par le portail. Construire un
lien direct vers un lab précis aurait demandé de router l'admission dans
une séance (SeanceController::admettre), bien plus complexe, pour un
besoin que le CLAUDE.md ne demande pas.
L'URL de lancement réutilise code_classe existant
(/lti/lancement/{code_classe}), pas un nouveau jeton ou une nouvelle
table de liaison. Exactement la même donnée que celle déjà affichée pour
« Faire rejoindre tes élèves » (code/QR) — LTI est juste une 6ᵉ porte vers
la même classe, pas un concept à part.
packbackbooks/lti-1p3-tool (Apache-2.0), recommandé par le CLAUDE.md.
Bibliothèque bas niveau (pas de dépendance à un framework) : il faut lui
fournir trois implémentations (ICache, ICookie, IDatabase, dans
App\Services\Lti\) qui s'appuient sur Redis, les cookies et les tables
lti_plateformes/lti_deploiements déjà en place.
Élève provisionné automatiquement au premier lancement, retrouvé par
(classe_id, lti_emetteur, lti_sub) ensuite — jamais de doublon de
compte à chaque connexion. Prénom/nom lus depuis les claims standards
(given_name/family_name, puis name, jamais inventés : « Élève » /
« Moodle » si Moodle n'envoie rien). Code secret généré au hasard, haché,
jamais affiché : cet élève se connecte toujours via Moodle, jamais par
identifiant/code comme les autres.
Cookie SameSite=None; Secure pour le jeton d'état OIDC. Sans ça, le
cookie ne survit jamais au POST final que Moodle envoie depuis son propre
domaine — chaque lancement échouerait silencieusement (« Please make sure
you have cookies… », message déjà prévu par la bibliothèque pour ce cas
précis, qui n'arrive qu'avec un réglage de cookie insuffisant).
Sécurité x-pack… non, pas de rapport ici — mais même logique que pour
Elasticsearch/Ceph : une seule clé RSA par plateforme Moodle enregistrée
(générée par le portail lui-même à l'enregistrement, phpseclib4\Crypt\RSA,
jamais collée par Adam), exposée en public via /lti/cles.json — c'est le
fonctionnement normal du protocole (Moodle doit pouvoir vérifier les jetons
que nous lui envoyons, si jamais le portail appelle un service LTI plus
tard), pas une fuite.
Enregistrement manuel, par commande Artisan, jamais une page
d'administration. Une plateforme Moodle se configure une fois par
établissement, par Adam, avec des informations lues dans l'administration
Moodle — une page web pour ça serait une fonctionnalité sans usage réel
(CLAUDE.md, section 8). lti:enregistrer-plateforme et
lti:enregistrer-deploiement, voir docs/runbooks/lti-moodle.md.
Conséquences
- Testé avec un jeton LTI réellement signé (RS256, paire de clés générée dans le test), jeu de clés de « Moodle » simulé : lancement validé de bout en bout, élève créé avec le bon prénom/nom, deuxième lancement du même élève ne crée pas de deuxième compte. Pas de vrai Moodle disponible pour vérifier en conditions réelles — à refaire dès qu'Adam a un Moodle de test.
- En dette : pas de web service LTI (AGS pour les notes, NRPS pour la
liste des inscrits, Deep Linking) — seul le lancement de ressource est
géré, comme décidé ci-dessus. Les classes de la bibliothèque pour ces
services existent déjà (
LtiAssignmentsGradesServiceetc.) si le besoin devient réel.