15 février 2026 · 6 min read

LTI Naming Role Provisioning Services (NRPS)

Comment retrouver les membres inscrits a un cours ou à une activité ?

#LTI #e-learning #standard #LMS

Names and Role Provisioning Services (NRPS)

Lorsqu’un étudiant clique sur une activité LTI, le LMS envoie un id_token à l’outil avec les informations de base sur l’utilisateur connecté : nom, prénom, email, rôle. Mais uniquement pour cet utilisateur. L’outil ne sait rien des autres membres du cours.

C’est un problème pour un outil de correction qui doit savoir qui doit rendre un devoir, ou un outil de présence qui doit afficher tous les inscrits, y compris ceux qui ne se sont jamais connectés. C’est là qu’intervient le service NRPS (Names and Role Provisioning Services) : il permet à l’outil d’interroger le LMS pour obtenir la liste complète des membres d’un cours à tout moment.

Le claim NRPS

Lorsqu’un administrateur souhaite autoriser un outil à accéder aux membres d’un cours, il doit le faire sur le LMS directement au moment de la registration LTI.

Exemple avec Moodle :

Moodle NRPS

Lorsqu’un individu clique sur l’activité LTI, le LMS envoie l’id token suivant :

{
"nonce": "eb50883ab09f4133a473aafd11481112510c474531f611f1b25d8cb87ec90090",
"iat": 1775506941,
"exp": 1775507001,
"iss": "http://localhost",
"aud": "Sfc6HFnwHAx4Tuv",
"https://purl.imsglobal.org/spec/lti/claim/deployment_id": "1",
"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": "LtiResourceLinkRequest",
"https://purl.imsglobal.org/spec/lti/claim/resource_link": {
"title": "Hello Django LTI",
"description": "",
"id": "1"
},
"https://purl.imsglobal.org/spec/lti-bo/claim/basicoutcome": {
"lis_result_sourcedid": "{\"data\":{\"instanceid\":\"1\",\"userid\":\"2\",\"typeid\":\"1\",\"launchid\":660104626},\"hash\":\"954bc429b7c122055ec07be48595dbd48cccd5cab99c822f25bad1d1be6dbdee\"}",
"lis_outcome_service_url": "http://localhost/mod/lti/service.php"
},
"given_name": "Admin",
"family_name": "Utilisateur",
"name": "Admin Utilisateur",
"https://purl.imsglobal.org/spec/lti/claim/ext": {
"user_username": "admin",
"lms": "moodle-2"
},
"email": "admin@localhost.fr",
"https://purl.imsglobal.org/spec/lti/claim/launch_presentation": {
"locale": "fr",
"document_target": "frame",
"return_url": "http://localhost/mod/lti/return.php?course=2&launch_container=5&instanceid=1&sesskey=6W3vqhmAD4"
},
"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",
"context_memberships_url": "http://localhost/mod/lti/services.php/CourseSection/2/bindings/1/memberships"
},
"https://purl.imsglobal.org/spec/lti-ags/claim/endpoint": {
"scope": [
"https://purl.imsglobal.org/spec/lti-ags/scope/lineitem",
"https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly",
"https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly",
"https://purl.imsglobal.org/spec/lti-ags/scope/score"
],
"lineitems": "http://localhost/mod/lti/services.php/2/lineitems?type_id=1",
"lineitem": "http://localhost/mod/lti/services.php/2/lineitems/2/lineitem?type_id=1"
},
"https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice": {
"context_memberships_url": "http://localhost/mod/lti/services.php/CourseSection/2/bindings/1/memberships",
"service_versions": [
"1.0",
"2.0"
]
}
}

on constate alors que la partie suivante a été ajoutée dans le token.

"https://purl.imsglobal.org/spec/lti-nrps/claim/namesroleservice": {
"context_memberships_url": "http://localhost/mod/lti/services.php/CourseSection/2/bindings/1/memberships",
"service_versions": [
"1.0",
"2.0"
]
}

Comme c’est le cas pour l’AGS, le LMS indique à l’outil que le service NRPS est disponible et fournit une URL pour récupérer les membres du cours.

Récupérer les membres

requête HTTP GET

Il s’agit d’un service en lecture seule. On peut utiliser uniquement la méthode GET pour récupérer les membres du cours. POST et PUT ne sont pas autorisés.

GET http://localhost/mod/lti/services.php/CourseSection/2/bindings/1/memberships
Authorization: Bearer <access_token>
Accept: application/vnd.ims.lti-nrps.v2.membershipcontainer+json

réponse du LMS

Les données renvoyées par le LMS sont les suivantes :

  • status : Le statut reflète l’état de l’inscription de l’utilisateur dans le cours, Les membres Inactive et Deleted sont renvoyés pour permettre à l’outil de synchroniser son propre état.
  • roles : Rôles dans le cours : Learner, Instructor, etc.
  • user_id : Identifiant unique de l’utilisateur dans le LMS
  • lis_person_sourcedid : Identifiant externe (SIS), souvent vide
  • name : Nom complet
  • given_name : Prénom
  • family_name : Nom de famille
  • email : Adresse email

Prenons l’exemple d’un cours sur Moodle ou il y a 3 inscrits.

  • Paul Bernier
  • Constance David
  • Marie Durand

comme le montre l’image ci-dessous :

image

Le cours est donc composé de 3 étudiants et un enseignant dans ce cours c’est l’admin Moodle.

Lorsque l’outil fait la requête présentée ci-dessus, le LMS , ici Moodle, répond avec la liste des membres du cours et leurs rôles respectifs :

{
"headers": {
"Date": "Wed, 08 Apr 2026 15:17:48 GMT",
"Server": "Apache/2.4.58 (Ubuntu)",
"Content-Length": "1095",
"Connection": "close",
"Content-Type": "application/vnd.ims.lti-nrps.v2.membershipcontainer+json; charset=utf-8"
},
"body": {
"id": "http://localhost/mod/lti/services.php/CourseSection/2/bindings/1/memberships",
"context": {
"id": "2",
"label": "pyLTI",
"title": "PYTHON LTI"
},
"members": [
{
"status": "Active",
"roles": [
"Learner"
],
"user_id": "4",
"lis_person_sourcedid": "",
"name": "paul Bernier",
"given_name": "paul",
"family_name": "Bernier",
"email": "paul.bernier@localhost.fr",
"ext_user_username": "paul"
},
{
"status": "Active",
"roles": [
"Learner"
],
"user_id": "5",
"lis_person_sourcedid": "",
"name": "Constance David",
"given_name": "Constance",
"family_name": "David",
"email": "constance.david@localhost.fr",
"ext_user_username": "constance"
},
{
"status": "Active",
"roles": [
"Learner"
],
"user_id": "3",
"lis_person_sourcedid": "",
"name": "marie durand",
"given_name": "marie",
"family_name": "durand",
"email": "marie.durand@localhost.fr",
"ext_user_username": "marie"
},
{
"status": "Active",
"roles": [
"Instructor",
"http://purl.imsglobal.org/vocab/lis/v2/person#Administrator"
],
"user_id": "2",
"lis_person_sourcedid": "",
"name": "Admin Utilisateur",
"given_name": "Admin",
"family_name": "Utilisateur",
"email": "admin@localhost.fr",
"ext_user_username": "admin"
}
]
},
"next_page_url": null
}

À chaque synchronisation, récupérer la liste complète des membres peut devenir coûteux pour un cours avec plusieurs centaines d’inscrits. NRPS propose un mécanisme d’optimisation : les membership differences.

Synchronisation des membres (membership differences)

Lors d’une réponse, le LMS peut inclure dans les headers HTTP un lien rel=“differences”

Link: <http://localhost/mod/lti/services.php/CourseSection/2/bindings/1/memberships?since=1744120668>; rel="differences"

L’outil stocke cette URL et l’utilise lors de sa prochaine synchronisation. Au lieu de récupérer l’intégralité des membres, il n’obtient que ce qui a changé depuis la création de cette URL

Il est également possible de filtrer les membres par rôle via le paramètre role ou de limiter le nombre de résultats avec limit. Pour le détail de ces paramètres, voir la spec NRPS v2.0.

Le Context Membership renvoie tous les membres du cours. Le Resource Link Membership affine cette liste au périmètre d’une ressource spécifique. Par exemple, généralement dans un LMS on peut limiter une activité à certain membres.

Moodle restriction d'activité

Ici par exemple l’activité Hello Django LTI est accessible seulement a Constance David

en effectuant la requête suivante :

GET http://localhost/mod/lti/services.php/CourseSection/2/bindings/1/memberships?rlid=1
Authorization: Bearer <access_token>
Accept: application/vnd.ims.lti-nrps.v2.membershipcontainer+json

C’est le même endpoint, avec le paramètre rlid en plus. La valeur de rlid vient du claim resource_link.id reçu dans l’id_token au lancement. C’est l’identifiant de l’activité.

on obtient la réponse du LMS sous la forme suivante

{
"id": "http://localhost/mod/lti/services.php/CourseSection/2/bindings/1/memberships",
"context": {
"id": "2",
"label": "pyLTI",
"title": "PYTHON LTI"
},
"members": [
{
"status": "Active",
"roles": ["Learner"],
"user_id": "5",
"lis_person_sourcedid": "",
"name": "Constance David",
"given_name": "Constance",
"family_name": "David",
"email": "constance.david@localhost.fr",
"ext_user_username": "constance",
"message": [
{
"https://purl.imsglobal.org/spec/lti/claim/message_type": "LtiResourceLinkRequest",
"https://purl.imsglobal.org/spec/lti-bo/claim/basicoutcome": {
"lis_result_sourcedid": "{\"data\":{\"instanceid\":\"1\",\"userid\":\"5\",\"typeid\":\"1\",\"launchid\":1768356591},\"hash\":\"3689eb51bff4dae69a127494a833190348eb7fccfcc2f00f19110803ea752736\"}",
"lis_outcome_service_url": "http://localhost/mod/lti/service.php"
}
}
]
},
{
"status": "Active",
"roles": [
"Instructor",
"http://purl.imsglobal.org/vocab/lis/v2/person#Administrator"
],
"user_id": "2",
"lis_person_sourcedid": "",
"name": "Admin Utilisateur",
"given_name": "Admin",
"family_name": "Utilisateur",
"email": "admin@localhost.fr",
"ext_user_username": "admin",
"message": [
{
"https://purl.imsglobal.org/spec/lti/claim/message_type": "LtiResourceLinkRequest",
"https://purl.imsglobal.org/spec/lti-bo/claim/basicoutcome": {
"lis_result_sourcedid": "{\"data\":{\"instanceid\":\"1\",\"userid\":\"2\",\"typeid\":\"1\",\"launchid\":1282032437},\"hash\":\"a15bc01883b85d0a3757f1f43c3e06a5e0ddb4e7b47b6fad3000fb7b1d280e7a\"}",
"lis_outcome_service_url": "http://localhost/mod/lti/service.php"
}
}
]
}
]
}

On constate qu’il n’y a plus que Constance David et l’enseignant mais que Paul et Marie n’apparaissent pas.

Si un étudiant , ici Constance David_ cliques sur l’activité, tout le flow décrit dans le post LTI dans les détails se déroule, l’outil reçoit un id_token avec les claims de base mais également un claim message qui contient des informations spécifiques à cette ressource. L’outils sait donc qui est inscrit à l’activité et qui a commencé l’activité. Cela lui permet de gérer les absences.

Partager