LTI Platform Support
Engine provides LTI platform support (import and launch of links into LTI tools) for LTI 1.1 and 1.3. The Engine concept of a "course" corresponds to the LTI concept of a "resource link".
Metadata
Occasionally you may want to pass additional information about the content to the tool as part of the launch process. This can be done by specifying metadata when making the request to import a course. The metadata schema is as follows:
"description": "string",
"context": {
"contextId": "string",
"contextTitle": "string",
"contextLabel": "string",
"contextType": [
"string"
]
},
"customParameters": [
{
"item": "string",
"value": "string"
}
]
All of the properties in the metadata schema, are optional, however, to use the Assignment and Grade Service in LTI 1.3, a contextId must be specified.
Note: In LTI, a context refers to a collection of resources, or what is commonly thought of as a course
A short description and example of each property is provided in the table below:
| Name | Description | Example |
|---|---|---|
| Context Id | Unique, opaque identifier for the context. For LTI 1.3, this identifier must not exceed 255 ASCII characters and must be provided if any other context claims are also provided | c1d887f0-a1a3-4bca-ae25-c375edcc131a |
| Context Title | Title for the context | Introduction To Calculus |
| Context Label | Short identifier for context such as a course code | MATH 1 |
| Context Type | The type of context the referenced link belongs to. Per LTI specifications, if this parameter is present the array must include at least one known context type for that LTI version. It may include other context types but by best practice they should be fully-qualified URNs (for LTI 1.1) or fully-qualified URIs (for LTI 1.3). | LTI 1.1 urn:lti:context-type:ims/lis/CourseOffering, CourseOffering, urn:lti:context-type:ims/lis/CourseSection, CourseSection, urn:lti:context-type:ims/lis/CourseTemplate, CourseTemplate, urn:lti:context-type:ims/lis/Group, Group. LTI 1.3 http://purl.imsglobal.org/vocab/lis/v2/course#CourseOffering, http://purl.imsglobal.org/vocab/lis/v2/course#CourseSection, http://purl.imsglobal.org/vocab/lis/v2/course#CourseTemplate, http://purl.imsglobal.org/vocab/lis/v2/course#Group |
| Custom Parameters | Custom parameters that will be included with the launch of the link. Per LTI specifications, if importing a version 1.1 link, the keys will be mapped to lowercase and all non-alphanumeric characters will be replaced with _ |
item: request_url value: https://tool.com/link/123 |
Custom Registration Parameters
As shown above, when importing an LTI course, one can set custom name/value pairs in the metadata's customParameters property, and Engine will send them to the Tool at runtime. However, it is possible to send custom parameters per registration in the event that the Tool has such a requirement.
To send custom parameters whose value could change from launch to launch, you first need to define the parameter names in the SupplementalQueryStringParametersForAllActivities setting, which takes a comma-delimited list. For example:
<entry key="SupplementalQueryStringParametersForAllActivities">first_name, last_name, age</entry>
<add key="SupplementalQueryStringParametersForAllActivities" value="first_name, last_name, age"/>
After defining the parameters name in SupplementalQueryStringParametersForAllActivities, you can add them them in the additionalValues property when generating a launch link:
{
"expiry": 10,
"redirectOnExitUrl": "https://example.org/myapp/courseDetail/12345",
"additionalValues": [
{
"item": "first_name",
"value": "Tom"
},
{
"item": "last_name",
"value": "Hardy"
},
{
"item": "age",
"value": "45"
}
]
}
Note: If you send parameters this way but already defined the same parameter name during import, Engine will use the registration-specific value from the launch link.
Optional Configuration Settings
The following configuration settings, if specified, will be passed to the LTI tool during launch:
- LtiConsumerProductFamily
- LtiConsumerVersion
- LtiConsumerName
- LtiConsumerDescription
- LtiConsumerUrl
- LtiConsumerEmail
LTI v1.3
Configuration
The following configuration settings are required for LTI 1.3 support:
- LtiConsumerIdentifier - A unique (a UUID is recommended) identifier for the product providing LTI support.
- LtiBaseUrl - A fully-qualified URL to the '/api' path under the Engine application. This value is used for determining absolute URLs for endpoints LTI 1.3 tools need to access.
- LtiPlatformIssuer An HTTPS URL identifying the LTI 1.3 platform.
JSON Web Tokens sent to the tool will have this value in the
issclaim, so tools should be configured to expect this value. - LtiPlayerPathUrl - Must be a fully qualified URL to Engine's
/defaultui/playerpath for LTI 1.3 platform support.- Note: This setting is not required if you already have a working absolute path for RemoteDeliverPageUrl, and Engine will fal back to using RemoteDeliverPageUrl if LtiPlayerPathUrl is not configured.
The following optional settings may also be specified:
- LtiJsonWebTokenExpiry
- EncryptionPassword - This setting should be specified so that the generated keys are stored encrypted.
- Lti13SubjectIdentifierFormat - Controls the format of the JWT
subclaim sent to the tool on launch and of theuserIdfield surfaced by the Assignment and Grade Service endpoints. Two values are supported:Legacy(default) - Thesub/userIdis a{scormRegistrationId}||{tenant}composite that uniquely identifies a single Engine registration. OneuserIdper registration.LearnerId- Thesub/userIdis the learner identifier supplied to the registration (Learner.Id). The same learner with multiple registrations for the same course will see a single, stableuserIdacross all of them; Engine resolves which registration a tool's request targets server-side. See User Ids for the resolution rules and the registration-scopedlineitemURL below for how a tool can target a specific registration explicitly.- Note: The
lti13SubjectIdentifiervalue reported by the/registrationsendpoints is recomputed on every read using the current setting value, so flipping the setting changes the value reported for existing registrations on that scope. The legacy{scormRegistrationId}||{tenant}userIdcontinues to be accepted by AGS endpoints regardless of the setting, so in-flight tools that cached aLegacyuserIdwill keep working until they re-launch.
Importing LTI 1.3 Links
Connector Import
An LTI 1.3 link may be imported only via Content Connector. The process of registering an LTI 1.3 tool with a connector involves two steps.
First, an LTI 1.3 connector must be created with a POST request to the /api/v2/contentConnectors endpoint with the following schema:
{
"contentConnectorType": "ContentConnector.Lti13",
"configuration": {
"toolPublicKey": "string",
"toolOidcLoginInitiationsEndpoint": "string",
"toolOidcLaunchRedirectUris": ["string"]
}
}
All of the fields in the schema are required.
toolPublicKey- The RSA 256 public key associated with the tool.toolOidcLoginInitiationsEndpoint- The endpoint the platform will use to initiate the OpenID Connect authorization flowtoolOidcLaunchRedirectUris- One or more URIs where the OIDC Authorization Response can be sent
A successful request will return the connectorId as a UUID in the response.
Second, the LTI 1.3 tool must be configured with information about the LTI 1.3 platform. This information can be retrieved by making a GET request to the /api/v2/contentConnectors endpoint with the includeAdditionalInstanceInformation=true query parameter and locating the entry corresponding to the connectorId from the first step. The response will contain an additionalInstanceInformation schema with the following keys:
"additionalInstanceInformation": {
"toolClientId": "string",
"oidcAuthorizationUrl": "string",
"jwksEndpoint": "string",
"issuer": "string",
"deploymentId": "string",
"accessTokenUrl": "string"
}
Each value (except accessTokenUrl) should be supplied to the LTI 1.3 tool to complete the registration process. accessTokenUrl is only needed if Assignment and Grade Services support is desired.
toolClientId- The OAuth Client Id for the tool. JSON Web Tokens sent to the tool will have this value in theaudclaim.oidcAuthorizationUrl- The endpoint where the tool should send the OIDC Authorization Request.jwksEndpoint- A link to access the platform's JSON Web Key Set. This will be an absolute, unsecured URL to the/plugin/lti13/{connectorId}/jwksendpoint.issuer- The value of the requiredLtiPlatformIssuerconfiguration setting.deploymentId- An identifier for the integration between the platform and the tool. Identical to theconnectorId.accessTokenUrl- The endpoint the tool should use to retrieve an OAuth 2.0 access token that it will use to access the platform's Assignment and Grade Services endpoints. This will be an absolute, unsecured URL to the/plugin/lti13/{connectorId}/tokenendpoint.
Once the connector has been created, an LTI 1.3 link can be imported using a POST request to the /api/v2/courses endpoint with the url and title passed in as follows:
{
"connectorReferenceRequest": {
"connectorId": "string",
"metadataForConnector": {
"url": "string",
"title": "string",
"ltiMetadata": {
"context": {
"contextId": "string"
}
}
}
}
}
The url in this schema is the endpoint that will be executed at the end of the OpenID Connect authentication flow. This value will be passed in the https://purl.imsglobal.org/spec/lti/claim/target_link_uri claim in the JSON Web Token.
Optional metadata can be specified with an ltiMetadata key in the metadataForConnector schema.
Once imported, the link may be launched through the normal course launch process.
Assignment and Grade Services
LTI 1.3 connectors provide support for recording and retrieving grades via the LTI Assignment and Grade Services specification. For the Assignment and Grade service to be used, a valid contextId should be supplied in the ltiMetadata API schema. The contextId should be a unique, opaque identifier for the context. For LTI 1.3, this identifier must not exceed 255 ASCII characters and must be provided if any other context claims are also provided. An example value for this property would be a guid like c1d887f0-a1a3-4bca-ae25-c375edcc131a.
Terminology
Line Items
Each LTI link imported into Engine corresponds to one line item. Different versions of the link will correspond to different line items. Currently, the tool is unable to create additional line items to associate with the link.
User Ids
The meaning of the userId carried in the JWT sub claim and surfaced by the AGS endpoints depends on the value of the Lti13SubjectIdentifierFormat configuration setting. In both cases, the userId produced for a given registration can be found by accessing the /registrations endpoint and locating the lti13SubjectIdentifier property.
Legacy format (default)
Each registration corresponds to exactly one userId. The value is a {scormRegistrationId}||{tenant} composite, so the userId is sufficient on its own to identify a single Engine registration. If a DELETE request is made to the /registrations/{registrationId}/progress endpoint, the tool will no longer be able to set or access grades for the userId corresponding to that registrationId. A new userId can be generated by re-launching the link for that registration.
LearnerId format
The userId is the learner identifier supplied to the registration, so a single learner with multiple registrations for the same course will share a single, stable userId across all of them. Engine resolves a (course, learnerId) pair to a registration server-side using the following rules:
- Multiple instances of the same
registrationIdare collapsed to the most-recent instance. - When the pair maps to multiple distinct
registrationIds, Engine selects the most recently updated registration.
Because userId no longer uniquely identifies a registration, the "DELETE progress → tool can no longer access grades for that userId" guarantee from the legacy format does not hold under LearnerId: if the same learner has another registration for the same course, the tool will still be able to read and write grades for that userId, against the surviving registration. Tools that need to target a specific registration explicitly should use the registration-scoped lineitem URL Engine includes in the launch JWT.
Authorization
Access Token
To access the Assignment and Grades endpoints, tools will need an OAuth 2.0 access token which can be requested using the /plugin/lti13/{connectorId}/token endpoint. A successful request will return a token with https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly, https://purl.imsglobal.org/spec/lti-ags/scope/score, and https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly and scopes, which will give the tool access to the following endpoints:
plugin/lti13/{connectorId}/{contextId}/lineItemsplugin/lti13/{connectorId}/{contextId}/lineItems/{lineItemId}plugin/lti13/{connectorId}/{contextId}/lineItems/{lineItemId}/scores(accepts an optionalregistrationIdquery parameter — see registration-scopedlineitemURL)plugin/lti13/{connectorId}/{contextId}/lineItems/{lineItemId}/results(accepts an optionalregistrationIdquery parameter whenuser_idis supplied — see registration-scopedlineitemURL)plugin/lti13/{connectorId}/{contextId}/lineItems/{lineItemId}/results/{userId}(accepts an optionalregistrationIdquery parameter — see registration-scopedlineitemURL)
Registration-scoped lineitem URL
Under Lti13SubjectIdentifierFormat=LearnerId, the AGS userId is the learner identifier rather than a per-registration composite, so a single (learner, course) pair can map to several registrations. To let a tool target a specific registration explicitly, Engine appends an opaque registrationId query parameter to the lineitem URL it includes in the launch JWT's https://purl.imsglobal.org/spec/lti-ags/claim/endpoint claim. Tools should treat the lineitem URL as opaque and pass it back verbatim on subsequent AGS requests, including the registrationId query parameter when it is present.
- Under
Legacy, the parameter is omitted from the launch JWT because the legacyuserIdalready uniquely identifies a registration. - The
registrationIdparameter is honored on:POST /lineItems/{lineItemId}/scoresGET /lineItems/{lineItemId}/results/{userId}GET /lineItems/{lineItemId}/results?userId=…— only whenuserIdis supplied. Per LTI-AGS 2.0 §3.3.3, a request to this endpoint withoutuserIdmust return all results for the line item, so Engine ignoresregistrationIdin that case.
registrationIdis not consulted onGET /lineItems/{lineItemId}or on the no-userIdform ofGET /lineItems/{lineItemId}/results. Tools that pass it on those calls will not get an error; the parameter is simply ignored.- When both
registrationId(query) anduserId(path / body /userIdquery) are supplied, Engine resolves the registration viaregistrationId. Engine validates that the targeted registration belongs to the line item's package and that the learner identifier for the registration matches the provideduserId; aregistrationIdthat fails this validation is rejected with a 400.
Grading
While the configured LTI tools will be able to read and write scores for line items using the endpoints defined above, limited information about LTI 1.3 registrations will also be available via the main Engine /registrations endpoints.
Registration Completion
The registrationCompletion value for an LTI 1.3 registration will be UNKNOWN if no scores have been received or if a score with the activityProgress value set to Initialized has been received . This value will be set to COMPLETED if the activityProgress value received is Completed or Submitted and to INCOMPLETE if the activityProgress value received is Started or InProgress.
Registration Success
Currently registrationSuccess for an LTI 1.3 registration will always contain UNKNOWN.
Recording Grades
An LTI 1.3 registration will be updated with the provided score if the gradingProgress value is set to FullyGraded, Pending, or PendingManual, provided that a score has actually been provided. In cases where either the scoreMaximum is 0, or the scoreMaximum is less than the scoreGiven, the scaled score will be set to NaN. Otherwise, the scaled score will be set to scoreGiven divided by scoreMaximum.
Extensions
Tools may add extensions when updating the score for a user. These extensions must be in the format of fully qualified URL properties added to the JSON object. For example, the following schema could be used when updating a score:
{
"timestamp": "2020-12-13T18:54:36.736+00:00",
"activityProgress" : "Completed",
"gradingProgress" : "FullyGraded",
"userId" : "123",
"https://www.exampletool.com/grading/english": {
"grammar": 6,
"spelling": 7,
}
}
In this case, https://www.exampletool.com/grading/english is the extension parameter. Any extensions posted with a score update will be saved and can be accessed through the main Engine /registrations endpoints by locating the lti13CustomClaims property. The lti13SubjectIdentifier in the registration schema is the value Engine produced for that registration's sub claim — under Legacy this uniquely identifies a single registration, while under LearnerId it is the learner identifier and may correspond to multiple registrations for the same (learner, course) pair (see User Ids).
Key Rotation
The LTI 1.3 connector provides a mechanism to rotate the RSA 256 key pairs associated with the platform. Rotation is done by making a POST request to /api/v2/plugin/lti13/{connectorId}/rotateKeys with the following body:
{
"expiry": "string"
}
expiry must be a valid UTC date-time
If the expiry time has not passed, a request to the /plugin/lti13/{connectorId}/jwks endpoint will return both the newly generated key and the previous key (for a maximum of two total keys at any given time). Once expiry passes, the endpoint will return a single key until another rotateKeys request with a non-expired expiry is made.
LTI v1.1
Configuration
The following configuration settings are required for LTI 1.1 support:
- LtiConsumerIdentifier - A unique (a UUID is recommended) identifier for the product providing LTI support.
- LtiBaseUrl - A fully-qualified URL to the '/api' path under the Engine application. This value is used for determining the absolute URL for the Basic Outcomes endpoint LTI 1.1 tools will use to report scores.
Importing LTI 1.1 Links
To import an LTI 1.1 link you will need the following information about it:
Consumer Key- The OAuth 1.0 Consumer Key supplied by the toolShared Secret- The OAuth 1.0 Secret supplied by the toolUrl- The Launch Url supplied by the toolTitle- A descriptive title for the content
Links may be imported either directly or with a connector. Both options are detailed below.
Once imported, the link may be launched through the normal course launch process and tracked via LTI Basic Outcomes.
Direct Import
An LTI 1.1 link may be imported directly using a POST request to api/v2/courses/. The minimal schema required for import is:
"lti11LinkReferenceRequest": {
"url": "string",
"key": "string",
"sharedSecret": "string",
"title": "string"
}
Optional metadata can be specified with an ltiLinkMetadata key in the lti11LinkReferenceRequest schema. Details can be found in the API documentation.
Connector Import
An LTI 1.1 link may also be imported via Content Connector. This is useful in cases where you have multiple links using the same credentials, because it allows you to specify the credentials in only one place.
An LTI 1.1 Content Connector can be created using a POST request to api/v2/ContentConnectors with the following information:
{
"contentConnectorType": "ContentConnector.Lti11",
"configuration": {
"key": "string",
"sharedSecret": "string"
}
}
A successful request to create a connector will return a UUID identifying the connector. This connectorId must be specified in subsequent requests to import content using the connector.
Once the connector has been created, an LTI 1.1 link can be imported using a POST request to the /api/v2/courses endpoint with the url and title passed in as follows:
{
"connectorReferenceRequest": {
"connectorId": "string",
"metadataForConnector": {
"url": "string",
"title": "string"
}
}
}
Optional metadata can be specified with an ltiMetadata key in the metadataForConnector schema.
Scoring
LTI 1.1 allows scores to be recorded on a scale from 0-1 via Basic Outcomes. In Engine these scores are scaled on a scale from 0-100. No completion information is recorded about LTI link launches.