CONECTORES / LTI 1.3

P2LRN LTI 1.3 Module

P2LRN includes a universal, self-hosted LTI 1.3 provider: it validates OIDC/JWT releases, publishes JWKS, offers catalog and Deep Linking, runs the same Player, persists state per learner/attempt, and can deliver grades via AGS. It is not a separate plugin for each LMS nor is it part of the course ZIP.

LTI 1.3 Provider Source Code

The technical ZIP includes the current code of integration/lms: cryptographic provider, HTTP server, SQLite store, AGS client, release and testing contracts. It also includes the Host Adapter needed to border with Player. It is not a specific Moodle/Canvas/Sakai/Chamilo/Open edX plugin nor a precompiled binary.

Requirements

Node.js 22.13+ and compiled Toolkit and Player distributions. A real deployment also requires a persistent RSA key, private storage, and a trusted HTTPS proxy.

Server

node integration/lms/lti-server.mjs starts the provider after setting its environment variables. By default it listens in loopback.

Security and interoperability

The provider includes JWT validation, issuer/audience, nonce/state, replay protection, Deep Linking, persistence, Player, AGS OAuth and isolation between institutions.

Self-hosted does not mean public shared service

p2lrn.org It is not a multi-institution LTI gateway to register directly to an LMS. Each deployment must host the provider in its own HTTPS URL, persist its keys, and explicitly register its trusted platforms.

Architecture: single player

LMS→Gateway LTI 1.3→Host Adapter→Player

The LMS maintains learners, teachers, registrations and gradebooks. The gateway verifies the identity and selects the published content; The Host Adapter manages loading and saving of state, events and notes. Player always opens the same .p2lrn, regardless of the LMS manufacturer.

OIDC – Secure Boot and Launch

  1. The administrator explicitly registers the platform using issuer, client_id, allowed deployments, authorization/token URLs and trusted JWKS keys.
  2. /lti/login create a transaction with state and nonce unique and short-lived.
  3. /lti/launch validates the RS256 signature and claims iss, aud/azp, exp, iat, version, type, deployment_id, target_link_uri and authorized binding.
  4. state and nonce They are consumed to block replay before creating the runtime session.

These checks live in the backend. The browser only receives a limited session for already authorized content.

JWKS and public keys

The provider publishes its keyring on /lti/jwks and sign Deep Linking responses with your persistent RSA key. To validate the LMS, it only uses keys belonging to trusted administrative records; a URL received from an unknown JWT does not become a trusted source.

The private keys, administrative token, SQLite, and package catalog remain off the public web and outside of each .p2lrn.

Deep Linking: choose course and lesson

The server implements protected catalog and selector. A teacher can choose a published course, unit, or activity and the provider returns a ltiResourceLink signed with a p2lrn_binding_id opaque tenant-bound, registration, deployment, package, contentRoot and entity.

Identidad portable

packageId + contentRoot + entityId identifies content and revision.

Deployment Binding

The opaque link avoids relying solely on resource_link.id, which can change when copying courses.

No Deep Linking

An administrator can create an authorized manual binding using POST /lti/admin/bindings and configure its opaque value as a custom LMS parameter.

Neither the teacher nor the learner can choose an arbitrary URL or entity to bypass the authorized catalog.

AGS: submit grades

The provider implements Assignment and Grade Services. The browser can report an observation, but an official note is only sent after the server validates it as authoritative. POST /lti/admin/grades records the decision and uses a persistent, idempotent outbox for OAuth2 submission.

Columna existente

With scope lineitem.readonly can locate and reuse a compatible column of the same resourceLinkId, respecting your scoreMaximum.

Create column

A new one is only created when the LMS explicitly granted write scope lineitem.

Retries

The faults remain in /lti/admin/ags/pending and can be retried without accepting redirections or destinations outside the registered LMS.

NRPS: roles and enrollments (optional)

NRPS remains optional and not currently implemented in this module. The LTI release roles are validated within the signed claims. learner roster synchronization should not be announced through NRPS until that service is implemented and tested.

Current provider status

Implemented: provider and persistence

createP2LRNLtiProvider(), createP2LRNLtiServer() and persistent SQLite for logs, deployments, catalog, bindings, transactions, sessions, attempts, status, events and AGS outbox.

Implemented: OIDC, JWKS, and Deep Linking

JWT signing/verification, state/nonce/replay, catalog, selector, and signed Deep Linking response.

Implemented: Player, state, and AGS

Authorized runtime, loading/saving state and events, intent inspection, OAuth2 AGS, secure lineitem reuse, and persistent retries.

Alcance actual: NRPS no incluido

NRPS is not part of this module. Compatibility with a particular installation of Moodle, Canvas, Sakai, Chamilo or Open edX must be validated against the actual LMS version, configuration and policies before using that integration.

Actual self-hosted server endpoints

The server implements /lti/login, /lti/launch, /lti/deep-link, /lti/deep-link/confirm, /lti/jwks, /lti/health, runtime and administration. Those routes belong to your provider deployment, not to the static P2LRN website.

Multi-institution security and isolation

  • Cryptographically validate JWT and verify iss, aud, azp, exp, iat, nonce, state, version, message type and deployment_id.
  • Consume each transaction only once; prevent replay and access between institutions or deployments.
  • Partition progress by institution, deployment, link, learner, attempt, package, review, and activity.
  • Do not expose private keys, LMS credentials, personal data, or tokens within a .p2lrn or browser URLs.
  • Refuse any access to unpublished content, non-existent activity or unauthorized service.
  • Verify the results on the server before transmitting official notes.

Implemented teacher and learner flow

Registro administrativo

The administrator registers a platform and explicit deployments, catalog and bindings; unknown senders/deployments are rejected.

Teacher selection

Deep Linking displays only published content and returns a signed resource linked to the review.

learner Launch

OIDC/JWT validates identity and deployment, creates a limited session and opens the same P2LRN Player.

Status and results

The runtime persists state/events per session and attempt. A validated grade decision can be sent to AGS via the outbox.

This loop is covered by the provider's automated HTTP tests. Checking against each actual LMS must also be performed on the installation and version to be used.

Pre-deployment check

  1. Build Toolkit and Player, generate a persistent RSA key and deploy the server over HTTPS; do not expose the administrative token, private key, SQLite, or package directory.
  2. Register issuer, client ID, deployment ID, URLs and JWKS of the real LMS instance; find out /lti/health and /lti/jwks.
  3. Publish a .p2lrn real in the catalog and verify Deep Linking or authorized manual binding.
  4. Test teacher and learner: login, launch, Player, resume, expiration, replay, access denied and course copy.
  5. When there is AGS, check the column and note in the actual book. Do not declare NRPS or universal compatibility where it has not been tested.
  6. Repeat the matrix with questionnaires, 3D games, SCORM/H5P, mobile and cookie/iframe policies of the specific version of the LMS.

More information about the standard at 1EdTech LTI. For platform differences, consult Conectores LMS.