15 février 2026 · 6 min read

LTI Course Groups Service

Gérer les groupes d'utilisateurs dans un contexte LTI

#LTI #e-learning #standard #Course Groups

LTI Course Groups Service : gérer les groupes d’utilisateurs dans un contexte LTI

Pourquoi Course Groups ?

Dans l’article sur NRPS, on a vu comment récupérer la liste des membres d’un cours. Mais les membres peuvent être organisés en groupes, par projet, par niveau, ou par tout autre critère. L’outil LTI doit connaître cette organisation pour adapter son comportement en fonction du groupe de l’utilisateur connecté. C’est nécessaire si l’outil a besoin de différencier les utilisateurs en fonction de leur groupe, par exemple pour afficher des contenus spécifiques à chaque groupe ou pour gérer des activités de groupe.

Par exemple dans un cours de programmation sur Python, les étudiants peuvent être répartis en groupes de projet (FastAPI, Django, Flask).

exemple de groupe dans moodle

Ces groupes peuvent être rassemblés dans un groupement. Par exemple, on pourrait avoir le groupement Projet contenant les groupes FastAPI, Django et Flask. C’est pratique pour restreindre une activité à un ensemble de groupes précis.

Ce mécanisme est utile dans d’autres contextes. Supposons qu’en Terminale, seuls les élèves ayant pris l’option Mathématiques Expertes ont accès aux cours sur les nombres complexes.

On aurait donc :

Structure cours mathématique terminale

On peut donc restreindre les cours sur les nombres complexes uniquement au groupe Mathématiques Expertes.

Un outil peut avoir besoin de récupérer ces groupes et c’est précisément ce que couvre la spécification LTI Course Groups Service - 1EdTech.

Le claim Course Groups

Comme pour AGS et NRPS, le LMS indique à l’outil que le service Course Groups est disponible directement dans l’id_token au moment du launch LTI :

"https://purl.imsglobal.org/spec/lti-gs/claim/groupsservice": {
"scope": [
"https://purl.imsglobal.org/spec/lti-gs/scope/contextgroup.readonly"
],
"context_groups_url": "https://www.myuniv.example.com/2344/groups",
"context_group_sets_url": "https://www.myuniv.example.com/2344/groups/sets",
"service_versions": ["1.0"]
}

Le claim contient :

  • context_groups_url : l’URL pour récupérer les groupes du cours. C’est le seul endpoint obligatoire.
  • context_group_sets_url : l’URL pour récupérer les groupements. Cet endpoint est optionnel, le LMS peut ne pas le supporter.
  • scope : le scope à demander pour obtenir un token d’accès. Le scope est readonly car le service est en lecture seule : l’outil ne peut que lire les groupes, pas les modifier.
  • service_versions : les versions du service supportées par le LMS.

Pour obtenir un token d’accès, voir l’article LTI Security.

Récupérer les groupes du cours

Requête HTTP GET

GET https://www.myuniv.example.com/2344/groups
Authorization: Bearer <access_token>
Accept: application/vnd.ims.lti-gs.v1.contextgroupcontainer+json

Réponse du LMS

{
"id": "https://www.myuniv.example.com/2344/groups",
"groups": [
{
"id": "44711f9f-64af-443a-bc3d-0abbfff73790",
"name": "FastAPI",
"tag": "project",
"set_ids": ["912cc53f-b431-447e-aff6-9d49aa9b72f2"]
},
{
"id": "bf2042b4-fdad-486a-86f3-bdb84e28a099",
"name": "Django",
"tag": "project",
"set_ids": ["912cc53f-b431-447e-aff6-9d49aa9b72f2"]
},
{
"id": "89230b3-a341-447e-aff6-9d354aa9b72a6",
"name": "Flask",
"tag": "project",
"set_ids": ["912cc53f-b431-447e-aff6-9d49aa9b72f2"]
}
]
}

Chaque groupe expose :

  • id : l’identifiant unique et stable du groupe
  • name : le nom lisible, à afficher à l’utilisateur
  • tag : la finalité du groupe, champ libre
  • set_ids : les identifiants des groupements auxquels appartient ce groupe

Le lien entre un groupe et son groupement se fait via set_ids. Pour connaître le nom du groupement, il faut faire un appel séparé sur context_group_sets_url.

Récupérer les groupes d’un utilisateur

L’outil connaît le user_id de l’étudiant connecté via le claim sub de l’id_token reçu au launch. Il peut l’utiliser pour filtrer directement les groupes de cet étudiant :

Requête HTTP GET

GET https://www.myuniv.example.com/2344/groups?user_id=0ae836b9-7fc9-4060-006f-27b2066ac545
Authorization: Bearer <access_token>
Accept: application/vnd.ims.lti-gs.v1.contextgroupcontainer+json

Réponse du LMS

{
"id": "https://www.myuniv.example.com/2344/groups?user_id=0ae836b9-7fc9-4060-006f-27b2066ac545",
"user_id": "0ae836b9-7fc9-4060-006f-27b2066ac545",
"groups": [
{
"id": "44711f9f-64af-443a-bc3d-0abbfff73790",
"name": "FastAPI",
"tag": "project",
"set_ids": ["912cc53f-b431-447e-aff6-9d49aa9b72f2"]
}
]
}

La réponse est le même format que précédemment, avec deux différences :

  • Le champ user_id est ajouté à la racine pour confirmer le filtre appliqué
  • Seuls les groupes de cet utilisateur sont retournés

Récupérer les groupements (Group Sets)

Si le LMS fournit un context_group_sets_url dans le claim, l’outil peut récupérer les groupements du cours :

Requête HTTP GET

GET https://www.myuniv.example.com/2344/groups/sets
Authorization: Bearer <access_token>
Accept: application/vnd.ims.lti-gs.v1.contextgroupsetcontainer+json

Réponse du LMS

{
"id": "https://www.myuniv.example.com/2344/groups/sets",
"sets": [
{
"id": "912cc53f-b431-447e-aff6-9d49aa9b72f2",
"name": "Projets Python"
}
]
}

Pour savoir quels groupes appartiennent à ce groupement, il faut parcourir la liste des groupes et filtrer par set_ids. Le groupement lui-même ne liste pas ses groupes.

Combiner NRPS et Course Groups

Il est possible de récupérer les membres du cours et leurs groupes en un seul appel NRPS, en ajoutant le paramètre groups=true :

Requête HTTP GET

GET https://www.myuniv.example.com/2344/memberships?groups=true
Authorization: Bearer <access_token>
Accept: application/vnd.ims.lti-nrps.v2.membershipcontainer+json

Réponse du LMS

{
"id": "https://www.myuniv.example.com/2344/memberships",
"context": { ... },
"members": [
{
"status": "Active",
"user_id": "0ae836b9-7fc9-4060-006f-27b2066ac545",
"name": "Alice Martin",
"roles": ["Learner"],
"group_enrollments": [
{"group_id": "44711f9f-64af-443a-bc3d-0abbfff73790"}
]
}
]
}

Chaque membre expose ses groupes via group_enrollments, un tableau d’objets contenant uniquement le group_id. L’appartenance à un groupe est binaire : un étudiant est dans un groupe ou il n’y est pas, il n’y a pas de rôle ou de condition.

Pagination

Comme pour NRPS, si le LMS ne peut pas retourner tous les groupes en une seule réponse, il inclut un header rel=next :

Link: https://www.myuniv.example.com/2344/groups/?p=2; rel=next

L’outil doit suivre ce lien pour récupérer la page suivante, jusqu’à ce que le header rel=next soit absent.

Variables de substitution : éviter les appels API

CourseGroup.id : le groupe sans appel API

Dans certains cas, l’outil n’a pas besoin d’appeler Course Groups du tout. Si l’enseignant a configuré l’activité LTI pour un groupe spécifique, le LMS peut injecter directement l’identifiant du groupe dans l’id_token via la variable de substitution CourseGroup.id :

"https://purl.imsglobal.org/spec/lti/claim/custom": {
"group_id": "$CourseGroup.id"
}

Au moment du launch, le LMS remplace $CourseGroup.id par l’identifiant du groupe associé au launch :

"https://purl.imsglobal.org/spec/lti/claim/custom": {
"group_id": "44711f9f-64af-443a-bc3d-0abbfff73790"
}

Deux points importants :

  • Si aucun groupe n’est associé au launch, la valeur sera une chaîne vide.
  • La présence de cette valeur ne signifie pas que l’utilisateur connecté est membre de ce groupe. Un enseignant peut lancer une activité de groupe sans en être membre.

Membership.course.groupIds : les groupes d’un utilisateur via substitution

De la même façon, il est possible de récupérer la liste des groupes d’un utilisateur directement dans l’id_token via Membership.course.groupIds :

"https://purl.imsglobal.org/spec/lti/claim/custom": {
"group_ids": "$Membership.course.groupIds"
}

Le LMS retourne une liste d’identifiants séparés par des virgules :

"https://purl.imsglobal.org/spec/lti/claim/custom": {
"group_ids": "44711f9f-64af-443a-bc3d-0abbfff73790,bf2042b4-fdad-486a-86f3-bdb84e28a099"
}

Ces identifiants correspondent aux group_id retournés par le service Course Groups. L’outil peut ainsi connaître les groupes de l’utilisateur connecté dès le launch, sans appel API supplémentaire.

Conclusion

Course Groups est un service complémentaire à NRPS. NRPS répond à “qui est dans le cours ?”, Course Groups répond à “comment sont-ils organisés ?”. Les deux ensemble permettent à un outil de connaître à la fois les membres, leurs rôles et leur organisation en groupes.

Selon le besoin, l’outil a trois façons d’obtenir les groupes d’un utilisateur :

  • récupérer tous les groupes du cours,
  • filtrer par user_id,
  • enrichir l’appel NRPS avec ?groups=true pour obtenir membres et groupes en une seule requête.

Dans les cas les plus simples, la variable de substitution $Membership.course.groupIds dans l’id_token évite même tout appel API.

Course Groups n’est pas encore supporté nativement par tous les LMS. Moodle en particulier ne l’implémente pas dans son cœur, mais un plugin tiersmoodle-ltiservice_memberships_celtic comble ce manque.


Sources :

Partager