ajoute Moodle LTI 1.3 (V2), une 6e façon de rejoindre une classe

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>
This commit is contained in:
Adam Belkacemi 2026-10-14 13:51:47 +02:00
parent 777dd1cbc8
commit 91d7cde4c1
27 changed files with 1293 additions and 9 deletions

View file

@ -17,6 +17,9 @@ use App\Http\Controllers\EleveTableauDeBordController;
use App\Http\Controllers\EmploiDuTempsController;
use App\Http\Controllers\EvenementExamenController;
use App\Http\Controllers\InscriptionController;
use App\Http\Controllers\LtiClesController;
use App\Http\Controllers\LtiConnexionController;
use App\Http\Controllers\LtiLancementController;
use App\Http\Controllers\MaClasseController;
use App\Http\Controllers\MesCoursController;
use App\Http\Controllers\MesDevoirsController;
@ -39,7 +42,6 @@ use App\Http\Controllers\SignalementController;
use App\Http\Controllers\TokenApiController;
use App\Http\Controllers\VisioController;
use App\Http\Controllers\WebdavAuthController;
use Illuminate\Foundation\Http\Middleware\ValidateCsrfToken;
use Illuminate\Support\Facades\Route;
Route::view('/', 'accueil')->name('accueil');
@ -55,11 +57,23 @@ Route::view('/inscription', 'auth.inscription')->name('register');
Route::view('/classes/suivi', 'classes.suivi')->name('suivi');
Route::view('/examen', 'examen')->name('examen');
// À brancher sur l'envoi d'e-mail (Mail::to('adam@belkacemi.me')->send(...)).
// Envoyé par les navigateurs eux-mêmes (pas de jeton CSRF possible).
// Envoyé par les navigateurs eux-mêmes (pas de jeton CSRF possible) :
// exclusion dans bootstrap/app.php (validateCsrfTokens), pas ici —
// "withoutMiddleware" sur la route elle-même ne suffit pas (419 constaté
// le 2026-10-14 en vérifiant /lti/lancement en réel).
Route::post('/csp-rapport', RapportCspController::class)
->withoutMiddleware(ValidateCsrfToken::class)
->middleware('throttle:30,1')
->name('csp.rapport');
// Moodle LTI 1.3 (V2, CLAUDE.md section 6) : postés directement par Moodle
// depuis son propre domaine, jamais de jeton CSRF à notre nom — la
// sécurité du lancement vient de la signature du jeton LTI lui-même.
// Exclusion dans bootstrap/app.php, voir le commentaire ci-dessus.
Route::match(['get', 'post'], '/lti/connexion', [LtiConnexionController::class, 'connecter'])
->name('lti.connexion');
Route::post('/lti/lancement/{codeClasse}', [LtiLancementController::class, 'lancer'])
->name('lti.lancement');
Route::get('/lti/cles.json', [LtiClesController::class, 'cles'])->name('lti.cles');
Route::post('/contact', fn () => back()->with('contact_ok', true))->name('contact');
Route::view('/fonctionnalites', 'fonctionnalites')->name('fonctionnalites');
Route::view('/legal', 'legal')->name('legal');