-
Notifications
You must be signed in to change notification settings - Fork 95
Description
Background
While testing H5P integration with Open edX using LTI 1.3, grade submision to the platform failed. The H5P team reported that their tool was receiving HTTP 500 errors when attempting to post grades back to Open edX. That investigation was tracked in an earlier issue #605.
Open edX logs suggested that H5P was submitting a malformed resource link id when calling the platform’s AGS endpoints. The value used by H5P had spaces where the actual resource id submitted during tool launch contained + characters.
ID in resource_link claim in tool launch: "https://purl.imsglobal.org/spec/lti/claim/resource_link": { "id": "block-v1:OpenedX+M101+2026+type@lti_consumer+block@1811877d79304c11b0ca1c6335de07a1"
Resource link ID used by H5P during grade submission: block-v1:OpenedX M101 2026 type@lti_consumer block@1811877d79304c11b0ca1c6335de07a1.
This caused parsing to fail in Open edX:
opaque_keys.InvalidKeyError: <class 'opaque_keys.edx.locator.CourseLocator'>: OpenedX M101 2026 type@lti_consumer block@1811877d79304c11b0ca1c6335de07a1
Logs for Ulmo sandbox when H5P submits grades: h5p_ulmo_grade_logs.txt
To work around the H5P issue, code was changed to send a URL-encoded value in the launch claim instead in this PR.
Modified ID in resource_link claim in tool launch: block-v1%3AOpenedX%2BCS51%2B2026%2Btype%40lti_consumer%2Bblock%408c8b7abfc6c44337af7d62899f398e57
This fixed the issue with H5P.
Realization
We now realize that the issue was with H5P, not Open edX. Because the LTI 1.3 spec requires resource link ID to be treated as "Opaque".
id (REQUIRED). Opaque identifier for a placement of an LTI resource link within a context that MUST be a stable and locally unique to the deployment_id.
This means that H5P should have used the exact same ID during submission, that it received during tool launch.
Problem
The change we made prevents other tools like Saltire, Ed Lessons etc. from posting grades back to the platform.
This is because, unlike H5P, these tools follow the spec and return the exact same resource link ID they got from the platform during launch.
That ID is URL-encoded and parser in Open edX is NOT expecting a URL-encoded resource link ID. You can observe this in the logs for when Ed Lessons attempts to submit grades to Open edX master sandbox: Edlessons_master_grade_logs.txt
The tables below show the resource link id sent by Open edX during launch and id used in AGS requests made by the tools. These examples are from the master sandbox after the change in PR #607.
| Tool | ID sent by Open edX in resource_link claim during tool launch |
|---|---|
| Ed Lessons | block-v1%3AOpenedX%2BCS51%2B2026%2Btype%40lti_consumer%2Bblock%40c0f1c50be4b8483f9e92cbb7a1e01cf7 |
| Saltire | block-v1%3AOpenedX%2BCS51%2B2026%2Btype%40lti_consumer%2Bblock%408c8b7abfc6c44337af7d62899f398e57 |
| H5P | block-v1%3AOpenedX%2BCS51%2B2026%2Btype%40lti_consumer%2Bblock%4030e75f786e9647e0af8a16b255310341 |
| Tool | ID sent by the tool to AGS endpoint |
|---|---|
| Ed Lessons | GET /api/lti_consumer/v1/lti/25/lti-ags?resource_link_id=block-v1%253AOpenedX%252BCS51%252B2026%252Btype%2540lti_consumer%252Bblock%2540c0f1c50be4b8483f9e92cbb7a1e01cf7 |
| Saltire | GET /api/lti_consumer/v1/lti/24/lti-ags?resource_link_id=block-v1%253AOpenedX%252BCS51%252B2026%252Btype%2540lti_consumer%252Bblock%25408c8b7abfc6c44337af7d62899f398e57 |
| H5P | GET /api/lti_consumer/v1/lti/28/lti-ags?resource_link_id=block-v1%3AOpenedX%2BCS51%2B2026%2Btype%40lti_consumer%2Bblock%4030e75f786e9647e0af8a16b255310341 |
Note that IDs sent by Saltire and Ed Lessons are double-encoded.
Proposed way forward
The most appropriate next step appears to be to revert the change introduced in PR #607, so that Open edX sends the actual resource link id in launch claim.
This will align Open edX implementation with the spec, which defines ID as an opaque value.
In parallel, H5P should be informed that its grade return flow appears to modify the resource link ID instead of treating it as opaque. H5P would need to preserve and reuse the exact value received during launch in order to comply with the spec.