This repository provides an Open edX LMS plugin for integrating external learning platforms and tools through the LTI 1.3 standard. It implements secure Resource Link launches, Deep Linking, and Assignment and Grade Services, enabling platforms to open Open edX course resources, add supported course links to their own environments, and exchange grades with the LMS. The plugin also provides the configuration, authentication, enrollment, and course access controls required to manage these integrations within Open edX.
This repository can be installed into Tutor by adding it as an extra pip requirement, rebuilding the openedx image, applying the required LMS settings, and running the plugin migrations. These instructions apply to Tutor local and production environments.
- Add the package to Tutor's extra pip requirements. Pinning to a tag or commit is recommended for reproducible builds:
tutor config save --append OPENEDX_EXTRA_PIP_REQUIREMENTS=git+https://github.com/Pearson-Advance/openedx-lti-tool-plugin.git@<TAG_OR_COMMIT>- Add the following production LMS settings to a new or existing Tutor plugin. See Tutor's plugin development tutorial for instructions on creating a plugin:
from tutor import hooks
hooks.Filters.ENV_PATCHES.add_item(
(
'openedx-lms-production-settings',
'OLTITP_ENABLE_LTI_TOOL = True',
'AUTHENTICATION_BACKENDS.append("openedx_lti_tool_plugin.auth.LtiAuthenticationBackend")',
)
)- If the plugin is not already enabled, enable it using its plugin name. Then regenerate the Tutor environment. Run
tutor config saveagain after every change to the plugin settings:
tutor plugins enable <PLUGIN_NAME>
tutor config save- Rebuild the Open edX image and launch the environment:
tutor images build openedx
tutor local launch- Apply the plugin's Django migrations, then restart the LMS:
tutor local run lms ./manage.py lms migrate openedx_lti_tool_plugin
tutor local restart lmsUse Tutor's development environment to bind-mount the repository into Open edX. Python source changes are then available inside the LMS container without rebuilding the image.
When testing with an external LTI platform, the development LMS must be reachable from that platform. You can expose it through a tunneling tool such as ngrok or cloudflared. You can also expose it through a reverse proxy. Both the tunneling tool and the reverse proxy must preserve the development environment's URL structure, including the LTI endpoints. The Tutor/Open edX host and URL settings must be configured so that the URLs advertised to the LTI platform match the public tunnel or proxy URLs. If the URL structure is changed, the Tutor deployment platform requires additional custom configuration that is outside the scope of this README. Alternatively, you can test without exposing the LMS publicly by using another LMS on the same network as the deployed Open edX development platform, provided that it can reach the development LMS.
For local testing without HTTPS, some LTI platforms may not be able to complete iframe-based workflows because browsers enforce secure-content and cookie restrictions. For example, Moodle's content selection feature may require the LMS to be available over HTTPS.
- Clone this repository and enter it:
git clone git@github.com:Pearson-Advance/openedx-lti-tool-plugin.git
cd openedx-lti-tool-plugin- Create a virtual environment and install the development dependencies. This environment is used for tests and code quality checks on the host; Tutor uses the package mounted into its containers.
python3 -m venv venv
source venv/bin/activate
make requirements- Register the repository as a Tutor mount and confirm that Tutor recognizes it for the
openedx-devimage and LMS services:
tutor mounts add "$(pwd)"
tutor mounts listThe mount list should include an openedx-dev build mount and an LMS compose mount for this repository.
- Add the following development LMS settings to a new or existing Tutor plugin. See Tutor's plugin development tutorial for instructions on creating a plugin:
from tutor import hooks
hooks.Filters.ENV_PATCHES.add_item(
(
'openedx-lms-development-settings',
'OLTITP_ENABLE_LTI_TOOL = True',
'AUTHENTICATION_BACKENDS.append("openedx_lti_tool_plugin.auth.LtiAuthenticationBackend")',
)
)- If the plugin is not already enabled, enable it using its plugin name. Then regenerate the Tutor environment. Run
tutor config saveagain after every change to the plugin settings:
tutor plugins enable <PLUGIN_NAME>
tutor config save- Build the development image and launch Tutor's development environment. The first build installs the mounted package in editable mode:
tutor images build openedx-dev
tutor dev launch- Apply the plugin's Django migrations, then restart the development LMS:
tutor dev run lms ./manage.py lms migrate openedx_lti_tool_plugin
tutor dev restart lms- Run the tests and code quality checks from the activated host virtual environment:
make test && make quality- Go to LMS Admin > PyLTI 1.3 Tool Config > Lti 1.3 tools.
- Create a new LTI 1.3 tool configuration with all your platform details.
- Go to your LTI platform and set the login and keyset URL of the LTI tool:
- Set the Resource Link launch URL on the platform to:
- Resource Link URL: https://lms-base/openedx_lti_tool_plugin/1.3/launch/
- Add
resourceId=RESOURCE_IDto the launch's LTI custom parameters. ReplaceRESOURCE_IDwith the complete Open edX course key or the usage key of the unit or problem to launch. Launching a complete course requires the "Complete Course Launch" feature. - Execute an LTI 1.3 Resource Link launch from the platform.
- The launch should take the user to the resource identified by
resourceId.
This LTI tool supports Deep Linking, allowing users to select Open edX content and add the resulting resource links to an LTI platform.
Currently, the Deep Linking service only supports selecting complete courses. Selecting individual units or problems from the LMS is not supported.
- Configure the LTI tool on the platform using the login and keyset URLs described above.
- Set the tool's Deep Linking URL on the platform to:
- Deep Linking URL: https://lms-base/openedx_lti_tool_plugin/1.3/deep_linking/
- Initiate an
LtiDeepLinkingRequestfrom the platform. - Select the Open edX content to add to the platform and submit the selection.
- The tool returns an
LtiDeepLinkingResponsecontaining the selected resource links to the platform.
This LTI tool supports AGS (Assignment and Grade Services) for both unit/problem and course resource link launches, AGS requires the LTI platform to send a line item and allow POST score updates, if no line item or POST score permission is sent, the resource link launch will fail requesting such configuration.
- LTI Assignment and Grade Services Specification: https://www.imsglobal.org/spec/lti-ags/v2p0
- Service Claims Example: https://www.imsglobal.org/spec/lti-ags/v2p0#example-link-has-a-single-line-item-tool-can-only-post-score
- OLTITP_ENABLE_LTI_TOOL: Enables or disables the LTI tool plugin.
- LtiAuthenticationBackend: Class needed to be added to AUTHENTICATION_BACKENDS.
- OLTITP_USERNAME_BASE_SOURCE: Source used to build a readable Open edX username on LTI launch. 'name' (default) uses the LTI name claim; 'email' uses the email claim prefix (text before @). When the chosen source is empty, the other source is used as a fallback. The base is normalized to Open edX username constraints (lowercase, alphanumeric, truncated to 20 characters). If the resulting username already exists (case-insensitive), a short UUID suffix is appended (e.g. jsmith.aB3xK9p2); when no source is available, a short UUID is used on its own.
- openedx_lti_tool_plugin.course_access_configuration: Toggles the "Course Access Configuration" feature.
- openedx_lti_tool_plugin.allow_complete_course_launch: Toggles the "Complete Course Launch" feature.
- openedx_lti_tool_plugin.save_pii_data: Toggles the "Save PII Data" feature.
By default, all resource links to all courses are allowed. If course access needs to be restricted you can set up a course access configuration policy for each LTI tool configuration deployed, this will allow you to set a list of allowed courses that an LTI tool configuration deployed is allowed for LTI 1.3 resource launches. Follow these next steps to set this feature:
- Enable the Django Waffle switch: openedx_lti_tool_plugin.course_access_configuration.
- Go to LMS Admin > Open edX LTI Tool Plugin > Course access configurations.
- On the configuration list, find the configuration that matches the previously created LTI tool.
- Edit the "Allowed Course IDs" field and add the courses that should be allowed.
By default, the LTI tool doesn't support LTI 1.3 resource launches over a complete Open edX course, with this feature, you can enable resource launches over a whole Open edX course, this will redirect the launch user to the Open edX learning MFE for the requested course: Follow these next steps to set this feature:
- Enable the Django Waffle switch: openedx_lti_tool_plugin.allow_complete_course_launch.
- Set the Resource Link launch URL on the platform to:
- Resource Link URL: https://lms-base/openedx_lti_tool_plugin/1.3/launch/
- Add
resourceId=course-v1:ORG+RUNto the launch's LTI custom parameters, replacingcourse-v1:ORG+RUNwith the course key to launch. - Execute the LTI 1.3 Resource Link launch on the platform.
- The launch should redirect the user to the course in the Open edX learning MFE.
By default, PII data is not obtained from launch data, this feature allows you to extract PII data from the standard OpenID Connect Standard Claims (https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) sent on the LTI 1.3 launch. Follow these next steps to set this feature:
- Enable the Django Waffle switch: openedx_lti_tool_plugin.save_pii_data.
- Set up an LTI 1.3 platform that uses claims such as email, name, given_name, family_name, and locale.
- Execute the LTI 1.3 launch on the platform.
- Go to LMS Admin > Open edX LTI Tool Plugin > LTI profiles.
- On the LTI profiles list, find the LTI profile that matches the Platform ID, Client ID, and Subject ID of your platform launch.
- The LTI profile should contain data on the PII JSON field.
By default, every user launched through an LTI 1.3 resource link is enrolled as a Student, regardless of the role declared by the platform. This feature reads the LTI 1.3 roles claim (https://www.imsglobal.org/spec/lti/v1p3#role-vocabularies) sent on the launch and translates it into an Open edX course-context role, respecting the trust boundary: the platform declares the role, and the Open edX operator decides per LTI tool configuration whether and how it is honored.
Role assignment is disabled by default and configured per LTI tool configuration, so it only applies to the platforms the operator explicitly decided to trust. Only course-context roles are honored; LTI system and institution roles are ignored (no system-wide grants). A missing, unrecognized or Learner role falls back to Student (enrollment only). The managed course role is reconciled on every launch, so a platform-side role change (e.g. Instructor downgraded to Learner) is reflected on Open edX instead of leaving the previously granted role in place. The default mapping is:
- http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor -> Course Instructor role (instructor).
- http://purl.imsglobal.org/vocab/lis/v2/membership#Administrator -> Course Staff role (staff).
- http://purl.imsglobal.org/vocab/lis/v2/membership#Learner -> Student (enrollment only).
Follow these next steps to set this feature:
- Go to LMS Admin > Open edX LTI Tool Plugin > LTI tool configurations.
- On the configuration list, find the configuration that matches the previously created LTI tool.
- Enable the "Enable role assignment" field.
- (Optional) Override the default mapping by editing the "Role mapping" JSON field. Keys are LTI role URIs and values are one of "instructor", "staff" or "student". Leave it empty to use the default mapping.
- Execute an LTI 1.3 resource link launch from the platform, sending the roles claim.
- Go to LMS Admin > Courses and confirm the launched user was granted the mapped course team role for the launched course.
The code in this repository is licensed under the Apache License 2.0 .
Please see LICENSE for details.