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)

Il arrive fréquemment que les outils d’apprentissage aient besoin de connaître la liste des membres d’un cours pour personnaliser l’expérience d’apprentissage. Par exemple, un outil peut proposer du travail collaboratif, il a donc besoin de savoir qui est inscrit dans le cours. L’outil peut également souhaiter créer automatiquement des espaces de travail séparés pour le “Groupe A” et le “Groupe B” sans aucune intervention humaine.

Sans NRPS, il faudrait que l’enseignant crée également le groupe d’utilisateur inscrit au cours dans l’outil si celui ci exige de travailler avec un groupe (pour du collaboratif ou autre), une fois que l’enseignant a créé les groupes il doit ajouter les utilisateurs. Cependant, ils n’ont pas de comptes sur l’outil, il faut gérer la création de compte sur l’outil. C’est ce que souhaite éviter LTI. C’est dans ce contexte que 1Edtech offre une solution de synchronisation d’une classe, cohorte et groupe inscrit à un cours, l’outil est au courant des membres et sait également qui a commencé l’activité.

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": "sebastien@philippot.co",
  "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 :

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

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": "sebastien@philippot.co",
        "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": "sebastien@philippot.co",
      "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