LTI DeepLinking
Offrez la possibilité de choisir vos exercices
DeepLinking (DL)
Comme nous l’avons vu dans le post LTI dans les détails, intégrer un outil LTI nécessite une étape de registration c’est-à-dire un échange d’informations entre l’outil et le LMS pour établir un lien de confiance. Une fois cette relation établie, un administrateur configure l’outil et les enseignants peuvent l’ajouter dans leurs cours autant de fois qu’ils le souhaitent. Le problème apparaît quand l’outil tiers propose un catalogue d’exercices. Chaque exercice nécessite sa propre configuration, donc son propre passage par la registration. Pour dix exercices, dix enregistrements. C’est un frein réel à l’adoption. C’est ce que Deep Linking résout. Au lieu de multiplier les configurations, l’enseignant lance l’outil directement depuis Moodle, navigue dans le catalogue proposé par l’outil, sélectionne l’exercice de son choix (ou plusieurs), et un lien direct vers cette ressource est automatiquement créé dans le cours.
Activer l’option deep linking dans le LMS
Lorsque un administrateur d’un LMS souhaite autorisé un outil à proposer un catalogue de ressources il doit le configurer au moment de la registration.
Par exemple avec Moodle :

Cela permet à l’enseignant de pouvoir choisir une ressource (exercice, video etc…). moodle présente un bouton Selectionner du contenu au moment d’intégrer l’outil dans un cours.

Le flux de lancement Deep Linking
Le lancement se déroule exactement de la même façon que le launch standard décrit dans le post LTI dans les détails avec pour seule différence le message_type du JWT qui vaut LtiDeepLinkingRequest au lieu de LtiResourceLinkRequest. C’est ce claim qui indique à l’outil qu’il ne doit pas afficher une ressource, mais proposer une interface de sélection.
Moodle initie la session exactement comme pour un launch classique, il crée un
formulaire HTML auto-soumis en POST vers l’endpoint de l’outil. L’enseignant est
redirigé vers l’outil avec un JWT signé contenant le contexte du cours, son
identité, ses rôles, et un claim supplémentaire deep_linking_settings qui décrit
ce que Moodle accepte comme types de retour.
L’outil prend alors le contrôle. Il vérifie le JWT comme il le ferait pour un launch standard, identifie l’enseignant et son contexte, puis affiche son interface de sélection — un catalogue d’exercices, un explorateur de ressources, un formulaire de création. La spec laisse l’outil entièrement libre sur cette expérience. Moodle peut ouvrir ce flux dans une iframe ou une popup pour que l’interface du cours reste visible en arrière-plan, mais ce n’est pas une obligation.
Une fois la sélection faite, l’outil construit un JWT de réponse — le
LtiDeepLinkingResponse — contenant la description de la ressource choisie, et le
POST vers l’URL deep_link_return_url fournie par Moodle dans le claim
deep_linking_settings. Moodle reçoit ce JWT, vérifie sa signature, et crée
l’activité dans le cours.
Un détail important : l’outil doit toujours rediriger vers deep_link_return_url,
même si l’enseignant n’a rien sélectionné. C’est ce qui permet à Moodle de fermer
proprement l’iframe ou la popup ouverte au départ.
Le LtiDeepLinkingRequest
Au moment du lauch l’id token devient :
{
"nonce": "fd6383991c494f1db873aea6eac5f7184933707b33d911f1b1cd8cb87ec90090",
"iat": 1775714375,
"exp": 1775714435,
"iss": "http://localhost",
"aud": "v6NOc0mEFNce1wI",
"https://purl.imsglobal.org/spec/lti/claim/deployment_id": "2",
"https://purl.imsglobal.org/spec/lti/claim/target_link_uri": "http://localhost:8000/lti/launch/",
"sub": "2",
"https://purl.imsglobal.org/spec/lti/claim/lis": {
"person_sourcedid": "",
"course_section_sourcedid": ""
},
"https://purl.imsglobal.org/spec/lti/claim/roles": [
"http://purl.imsglobal.org/vocab/lis/v2/institution/person#Administrator",
"http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor",
"http://purl.imsglobal.org/vocab/lis/v2/system/person#Administrator"
],
"https://purl.imsglobal.org/spec/lti/claim/context": {
"id": "2",
"label": "pyLTI",
"title": "PYTHON LTI",
"type": [
"CourseSection"
]
},
"https://purl.imsglobal.org/spec/lti/claim/message_type": "LtiDeepLinkingRequest",
"https://purl.imsglobal.org/spec/lti/claim/launch_presentation": {
"locale": "fr"
},
"https://purl.imsglobal.org/spec/lti/claim/ext": {
"lms": "moodle-2"
},
"https://purl.imsglobal.org/spec/lti/claim/tool_platform": {
"product_family_code": "moodle",
"version": "2025100603.11",
"guid": "aa85caf65877b6e8f2e5cfd314c9805e",
"name": "local",
"description": "localhost"
},
"https://purl.imsglobal.org/spec/lti/claim/version": "1.3.0",
"https://purl.imsglobal.org/spec/lti/claim/custom": {
"niveau": "Terminale",
"debut_cours": "2026-04-03T23:00:00+00:00",
"fin_cours": "2027-04-03T23:00:00+00:00"
},
"https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings": {
"accept_types": [
"ltiResourceLink"
],
"accept_presentation_document_targets": [
"frame",
"iframe",
"window"
],
"accept_copy_advice": false,
"accept_multiple": true,
"accept_unsigned": false,
"auto_create": false,
"can_confirm": false,
"deep_link_return_url": "http://localhost/mod/lti/contentitem_return.php?course=2&id=2&sesskey=ifDNXFlCBh",
"title": "Django - LTI DL",
"text": ""
}
}
On remarque deux choses :
- Le messageType devient
"https://purl.imsglobal.org/spec/lti/claim/message_type": "LtiDeepLinkingRequest"au lieu de"https://purl.imsglobal.org/spec/lti/claim/message_type": "LtiResourceLinkRequest"pour un launch classique. - L’ajout du claim
"https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settingspermet de spécifier les paramètres de l’outil de création de lien profond.
"https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings": {
"accept_types": [
"ltiResourceLink"
],
"accept_presentation_document_targets": [
"frame",
"iframe",
"window"
],
"accept_copy_advice": false,
"accept_multiple": true,
"accept_unsigned": false,
"auto_create": false,
"can_confirm": false,
"deep_link_return_url": "http://localhost/mod/lti/contentitem_return.php?course=2&id=2&sesskey=ifDNXFlCBh",
"title": "Django - LTI DL",
"text": ""
}
-
accept_typesliste les types de ressources que Moodle peut recevoir. Ici["ltiResourceLink"]— Moodle attend un lien vers une ressource LTI. C’est le type le plus courant et le seul que Moodle supporte dans cette configuration. -
accept_presentation_document_targetsindique dans quels contextes d’affichage Moodle pourra intégrer la ressource retournée —frame,iframeouwindow. L’outil peut utiliser cette information pour n’exposer dans son catalogue que les ressources compatibles avec ces modes d’affichage. -
accept_multipleàtruesignifie que l’outil peut retourner plusieurs ressources en une seule session. L’enseignant pourrait sélectionner trois exercices d’un coup et Moodle créerait trois activités dans le cours. Si ce champ est àfalse, l’outil doit limiter la sélection à un seul item. -
auto_createàfalseest important. Quand il est àtrue, Moodle crée immédiatement l’activité dans le cours sans demander confirmation à l’enseignant. Àfalse, Moodle présente d’abord un aperçu avant de créer le lien. Dans un environnement de production, laisser ce champ àfalseest plus sûr. -
accept_unsignedàfalsesignifie que Moodle exige que le JWT de réponse soit signé par l’outil avec sa clé privée. Ne jamais passer ce champ àtrueen production. -
deep_link_return_urlest l’URL vers laquelle l’outil doit poster sa réponse une fois la sélection terminée. L’outil doit conserver cette URL tout au long de son flux de sélection. -
titleettextsont des suggestions du LMS pour pré-remplir le titre et la description de la ressource dans l’interface de l’outil. L’outil peut les ignorer.
Le LMS affiche alors la page renvoyé par l’outils. Il s’agit d’une page HTML représentant un catalogue de ressource.

Le LtiDeepLinkingResponse
Une fois l’enseignant a sélectionné sa ressource, l’outil construit un JWT signé
avec sa clé privée et le poste vers la deep_link_return_url via un formulaire
HTML auto-soumis.
<form
id="lti13_deep_link_auto_submit"
action="http://localhost/mod/lti/contentitem_return.php?course=2&id=2&sesskey=ifDNXFlCBh"
method="POST"
>
<input type="hidden" name="JWT" value="eyJ0eXAiOiJKV1Qi..." />
</form>
<script type="text/javascript">
document.getElementById("lti13_deep_link_auto_submit").submit();
</script>
L’action du formulaire est exactement la deep_link_return_url reçue dans le
claim deep_linking_settings. Le JWT est posté dans un champ caché nommé JWT.
Le script soumet le formulaire sans aucune interaction de l’enseignant, il est
redirigé automatiquement vers Moodle qui reçoit la réponse.
Une fois décodé, le JWT contient :
{
"iss": "v6NOc0mEFNce1wI",
"aud": [
"http://localhost"
],
"exp": 1775762232,
"iat": 1775761632,
"nonce": "nonce-349d991133b044a896847b62f53d1f4f50c92e71344711f198a08cb87ec90090",
"https://purl.imsglobal.org/spec/lti/claim/deployment_id": "2",
"https://purl.imsglobal.org/spec/lti/claim/message_type": "LtiDeepLinkingResponse",
"https://purl.imsglobal.org/spec/lti/claim/version": "1.3.0",
"https://purl.imsglobal.org/spec/lti-dl/claim/content_items": [
{
"type": "ltiResourceLink",
"title": "Variables et types",
"url": "http://localhost:8000/lti/launch/",
"custom": {
"exercice": "variables"
}
}
],
"https://purl.imsglobal.org/spec/lti-dl/claim/data": null
}
iss et aud sont inversés par rapport au request car c’est maintenant l’outil
qui s’identifie comme émetteur et Moodle comme destinataire. Moodle vérifie la
signature avec la clé publique de l’outil déclarée lors de la registration.