Skip to Content
Interop EdTechPartie 10 — LTI Advantage10.4 — NRPS : lire le roster

Chapitre 10.4 — NRPS : lire le roster

⏱️ TL;DRNRPS (Names and Role Provisioning Services) laisse ton outil lire la liste des membres d’un cours — le roster — et leurs rôles, sans que l’enseignant ressaisisse quoi que ce soit. Le lancement livre l’endpoint dans le claim .../lti-nrps/claim/namesroleservice = { "context_memberships_url": "URL", "service_versions": [...] }. On fait GET {context_memberships_url} (avec un access_token de scope .../lti-nrps/scope/contextmembership.readonly) et on reçoit un conteneur members : pour chaque membre, user_id, roles, status, et — si la plateforme les partagename et email. La liste peut être paginée (en-tête Link avec rel="next"). Cas d’usage : pré-remplir la classe, afficher un tableau de suivi. Mais un roster, ce sont des données personnelles de mineurs : ne lis et ne stocke que le nécessaire (RGPD).

🎯 Objectifs

  • Lire le claim namesroleservice et appeler context_memberships_url.
  • Interpréter le conteneur members (user_id, roles, status, name/email).
  • Gérer la pagination (en-tête Link, rel="next").
  • Décider quelles données lire et conserver — et lesquelles laisser (confidentialité).

Le problème : connaître la classe

Ton outil affiche un tableau de suivi à l’enseignant : une ligne par élève, avec sa progression. Mais au premier lancement, ton outil ne connaît que l’utilisateur qui vient de cliquer (son sub). Comment lister toute la classe sans que l’enseignant tape 28 noms à la main ?

NRPS répond : ton outil demande le roster à la plateforme. Il obtient la liste des membres du contexte (le cours), avec leurs rôles et leur statut. Tu peux alors pré-remplir ta classe, préparer une ligne par élève, afficher qui est enseignant et qui est apprenant — le tout avant même que les élèves se connectent.

Le claim namesroleservice

Comme pour AGS, l’endpoint arrive dans le id_token du lancement :

{ "https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice": { "context_memberships_url": "https://moodle.ecole.fr/mod/lti/services.php/CtxMemberships.php/2?type=Membership", "service_versions": ["2.0"] } }
  • context_memberships_url : l’URL du roster de ce cours. C’est elle qu’on interroge.
  • service_versions : les versions de NRPS supportées par la plateforme (ici 2.0).

Lire le roster

Un GET, avec un access_token de scope .../lti-nrps/scope/contextmembership.readonly :

GET /mod/lti/services.php/CtxMemberships.php/2?type=Membership HTTP/1.1 Host: moodle.ecole.fr Authorization: Bearer eyJ0eXAi... Accept: application/vnd.ims.lti-nrps.v2.membershipcontainer+json

La réponse est un conteneur de membres :

{ "id": "https://moodle.ecole.fr/mod/lti/services.php/CtxMemberships.php/2", "context": { "id": "course-9271", "label": "MATH-6A", "title": "Mathematiques 6e A" }, "members": [ { "user_id": "u-2342", "roles": ["http://purl.imsglobal.org/vocab/lis/v2/membership#Learner"], "status": "Active", "name": "Camille Martin", "email": "camille.martin@ecole.fr" }, { "user_id": "u-1088", "roles": ["http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor"], "status": "Active", "name": "Sofia Nkosi" }, { "user_id": "u-7751", "roles": ["http://purl.imsglobal.org/vocab/lis/v2/membership#Learner"], "status": "Inactive" } ] }

Décryptage :

  • Le conteneur porte un context (le cours : id, label, title) et un tableau members.
  • Chaque membre a :
    • user_id : l’identifiant stable de l’utilisateur chez la plateforme. C’est le même que le sub reçu quand cet utilisateur lance ton outil (chapitre 9.5). C’est la clé pour recoller roster et notes.
    • roles : un tableau d’URIs de rôles (mêmes valeurs qu’au lancement : ...#Learner, ...#Instructor…). Un membre peut cumuler plusieurs rôles.
    • status : Active, Inactive ou Deleted. Un élève désinscrit apparaît Inactive/Deleted.
    • name / email : présents seulement si la plateforme accepte de les partager (voir plus bas). Dans l’exemple, l’enseignant Sofia n’a pas d’email partagé, et l’élève u-7751 n’a ni nom ni e-mail.

⚠️ Piège — Supposer que name et email sont toujours là. Ils sont facultatifs : beaucoup de plateformes, surtout pour des mineurs, ne partagent que user_id, roles et status. Un outil qui plante faute d’e-mail est un outil qui ne passe pas la revue de sécurité d’une académie. Traite name/email comme absents par défaut et n’utilise que user_id comme identifiant.

⚠️ Piège — Recoller roster et notes via l’e-mail ou le nom. Utilise user_id (= le sub du lancement). L’e-mail change, manque, ou n’est pas partagé ; le nom n’est pas unique. user_id est la seule clé fiable et stable.

Filtrer et paginer

Deux paramètres utiles sur context_memberships_url :

  • Filtre par rôle : ?role=...#Instructor pour ne récupérer que les enseignants (ou ?role=...#Learner pour les élèves). Pratique et économe.
  • Pagination : un gros cours renvoie les membres par pages. La page suivante n’est pas un numéro dans le JSON : c’est un en-tête HTTP Link avec rel="next".
HTTP/1.1 200 OK Content-Type: application/vnd.ims.lti-nrps.v2.membershipcontainer+json Link: <https://moodle.ecole.fr/mod/lti/services.php/CtxMemberships.php/2?rlid=res-4815&page=2>; rel="next" { "id": "...", "context": { }, "members": [ ] }

Tu lis la page, puis, tant qu’il y a un Link ... rel="next", tu suis l’URL fournie et tu concatènes les members. Quand l’en-tête next disparaît, tu as tout le roster.

💡 RéflexeSuis toujours la pagination. Un dev qui lit « la première page » croit avoir 20 élèves alors que la classe en compte 45. Boucle sur rel="next" jusqu’à épuisement, et n’invente pas de ?page= toi-même : utilise l’URL exacte donnée dans l’en-tête Link (elle peut porter des paramètres opaques).

Cas d’usage

BesoinComment NRPS aide
Pré-remplir la classeRécupérer tous les Learner Active pour préparer une ligne de suivi par élève, avant leurs connexions.
Tableau de bord enseignantCroiser le roster (NRPS) avec les notes (AGS) via user_id = clé : afficher « qui a fait quoi, avec quel score ».
Afficher la listeMontrer les membres et leurs rôles (distinguer profs et élèves).
NettoyerMarquer Inactive/Deleted les élèves désinscrits, ne plus leur pousser de contenu.

🔒 Confidentialité — Un roster de cours scolaire, ce sont des données personnelles de mineurs. Le partage de name/email est un réglage de la plateforme, pas un dû. Applique la minimisation : si user_id suffit à ton usage (recoller les notes), ne demande pas et ne stocke pas les noms/e-mails. Cette discipline relève du RGPD — et une académie la vérifie avant de te déployer.

🔌 Côté intégration — NRPS transforme l’expérience enseignant : au lieu d’attendre que chaque élève se connecte pour « exister » dans ton outil, la classe est là dès le premier lancement. Combiné à l’AGS, ça donne un vrai tableau de suivi (roster × notes) — l’argument qui fait dire à un chef d’établissement « celui-là, on le garde ». La certification NRPS vérifie que tu gères correctement la pagination, les rôles et l’absence de name/email.

🧭 Sur FormaCampus — Au lancement enseignant (rôle #Instructor), le studio lit namesroleservice, obtient un access_token (scope contextmembership.readonly) et GET le roster de 6e A. Il récupère 28 Learner Active (dont beaucoup sans e-mail — la plateforme protège les mineurs), boucle sur rel="next" pour la 2ᵉ page, et pré-remplit son tableau : une ligne par élève, indexée sur user_id. Quand les scores remontent via AGS (10.3), le studio les place en face du bon user_id. L’enseignant voit sa classe complète, avec ou sans notes, sans avoir tapé un seul nom. Et le studio ne conserve pas les e-mails, qu’il n’utilise pas.

📚 La spec — NRPS est spécifié par LTI Names and Role Provisioning Services (1EdTech). Le claim .../lti-nrps/claim/namesroleservice (context_memberships_url, service_versions), le conteneur members (user_id, roles, status, name/email optionnels), le type de média application/vnd.ims.lti-nrps.v2.membershipcontainer+json, le filtre role et la pagination par en-tête Link sont normés. Scope : .../lti-nrps/scope/contextmembership.readonly. Détails sur 1edtech.org.

✏️ Exercices

Exercice 1 — Lis le roster. Dans le conteneur members de l’exemple, combien d’élèves actifs ton outil doit-il afficher, et qu’utilises-tu comme identifiant pour chacun ?

✅ Solution

Un seul élève actif à afficher : u-2342 (Camille), qui a ...#Learner et status: "Active". u-1088 est enseignant (#Instructor), pas un élève. u-7751 est un Learner mais Inactive (désinscrit) — à ne pas afficher comme élève actif. L’identifiant est user_id (u-2342), pas l’e-mail ni le nom.

Exercice 2 — Pagination. Ta première requête NRPS renvoie 20 membres et un en-tête Link: <...page=2>; rel="next". La classe fait 45 élèves. Que fais-tu ?

✅ Solution

Tu n’as pas tout le roster. Tu dois suivre l’URL exacte donnée dans l’en-tête Link (rel="next"), faire le GET suivant (avec le même bearer), concaténer ses members, et répéter tant qu’un en-tête rel="next" est présent. Quand il disparaît, tu as les 45. Ne fabrique pas toi-même ?page=3 : utilise l’URL fournie, qui peut contenir des paramètres opaques.

Exercice 3 — Minimisation. La plateforme partage name et email de mineurs. Ton outil n’a besoin que de recoller les notes au bon élève. Que lis-tu, que stockes-tu ?

✅ Solution

Pour recoller les notes, user_id suffit (c’est la clé partagée avec l’AGS). Tu peux lire le conteneur, mais tu ne conserves que user_id (et éventuellement roles/status pour l’affichage). Tu ne stockes pas name/email, dont tu n’as pas l’usage : c’est le principe de minimisation du RGPD, particulièrement critique pour des mineurs, et un point vérifié par les académies avant déploiement.

🧠 Quiz de révision

1. Dans quel claim, et à quelle URL, lit-on le roster ?

Dans le claim .../lti-nrps/claim/namesroleservice, champ context_memberships_url. On y fait un GET avec le scope .../lti-nrps/scope/contextmembership.readonly.

2. Que contient chaque membre du conteneur members ?

user_id (identifiant stable), roles (tableau d’URIs), status (Active/Inactive/Deleted), et si partagés name/email. user_id correspond au sub du lancement de ce membre.

3. Comment gère-t-on un gros roster ?

Par pagination : la page suivante est donnée dans l’en-tête HTTP Link avec rel="next". On suit cette URL jusqu’à ce qu’il n’y ait plus de next. On peut aussi filtrer par ?role=....

4. Peut-on compter sur name et email ?

Non. Ils sont optionnels et souvent absents (protection des mineurs, réglage de confidentialité de la plateforme). On traite name/email comme absents par défaut et on n’utilise que user_id comme identifiant.

5. Quelle donnée relie roster (NRPS) et notes (AGS) ?

Le user_id du membre (NRPS) est le même que le userId du Score et le sub du lancement (AGS). C’est la clé qui permet d’afficher, en face de chaque élève, sa note.


Chapitre suivant : Sécurité & conformité — clés, scopes, rotation, et la certification 1EdTech qui ouvre les marchés.

Last updated on