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>
76 lines
4 KiB
Markdown
76 lines
4 KiB
Markdown
# 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à (`LtiAssignmentsGradesService` etc.) si le besoin
|
|
devient réel.
|