ims-lti
This is a nodejs library used to help create Tool Providers for the IMS LTI standard. Tool Consumer implmentation is left as an excersise to the reader :P
Install
npm install ims-lti --save
To require the library into your project
require 'ims-lti'
Supported LTI Versions
- 1.0 - Implementation Guide
- 1.1 - Implementation Guide
- 1.1.1 - Implementation Guide
Usage
The LTI standard won't be covered here, but it would be good to familiarize yourself with the specs. LTI documentation
This library doesn't help you manage or distribute the consumer keys and secrets. The POST
parameters will contain the oauth_consumer_key
and your application should use that to look up the consumer secret from your own datastore.
This library offers a few interfaces to use for managing the OAuth nonces to make sure the same nonce isn't used twice with the same timestamp. Read the LTI documentation on OAuth. They will be covered below.
Setting up a Tool Provider (TP)
As a TP your app will receive a POST request with LTI launch data that will be signed with OAuth using a key/secret that both the TP and Tool Consumer (TC) share. This is all covered in the LTI security model
Once you find the oauth_consumer_secret
based on the oauth_consumer_key
in the POST request, you can initialize a Provider
object with them and a few other optional parameters:
lti = require 'ims-lti' provider = consumer_keyconsumer_secretnonce_store=MemoryStoresignature_method=HMAC_SHA1
Once the provider has been initialized, a reqest object can be validated against it. During validation, OAuth signatures are checked against the passed consumer_secret and signautre_method ( HMAC_SHA1 assumed ). isValid returns true if the request is an lti request and is properly signed.
providervalid_request req # isValid = Boolean | always false if err # err = Error object with method descibing error if err, null if no error
After validating the reqest, the provider object both stores the requests parameters (excluding oauth parameters) and provides convinience accessors to common onces including provider.student
, provider.ta
, provider.username
, and more. All request data can be accessed through provider.body
in an effort to namespace the values.
Currently there is not an emplementation for posting back to the Tool Consumer, although there is a boolean accessor provider.outcome_service
that will return true if the TC will accept a POSTback.
Nonce Stores
ims-lti
does not standardize the way in which the OAuth nonce/timestamp is to be stored. Since it is a crutial part of OAuth security, this library implements an Interface to allow the user to implement their own nonce-stores.
Nonce Interface
All custom Nonce stores should extend the NonceStore class and implment isNew
and setUsed
: # Sets any new nonce to used :
Two nonce stores have been implemented for convinience.
MemoryNonceStore
The default nonce store (if none is specified) is the Memory Nonce Store. This store simply keeps an array of nocne/timestamp keys. Timestamps must be valid within a 5 minute grace period.
RedisNonceStore
A superior nonce store is the RedisNonceStore. This store requires a secondary input into the constructor, a redis-client. The redis client is used to store the nonce keys and set them to expire within a set amount of time (default 5 minutes). A RedisNonceStore is initialized like:
RedisNonceStore = require '../lib/redis-nonce-store'client = require'redis'createClientstore = 'consumer_key'client provider = consumer_keyconsumer_secretstore
Outcomes Extension
The outcomes feature is part of the LTI 1.1 specification and is new to ims-lti 1.0. All of the behind-the-scenes work necessary to get the ball rolling with it is already implemented for you, all you need to do is submit grades.
provider = consumer_keyconsumer_secret providervalid_request req # Check if the request is valid and if the outcomes service exists. if !is_valid || !provideroutcome_service return false # Check if the outcome service supports the result data extension using the # text format. Available formats include text and url. consolelog provideroutcome_servicesupports_result_data'text' # Replace accepts a value between 0 and 1. provideroutcome_servicesend_replace_result 5 consolelog result # True or false provideroutcome_servicesend_read_result consolelog result # Value of the result already submitted from this embed provideroutcome_servicesend_delete_result consolelog result # True or false provideroutcome_servicesend_replace_result_with_text 5'Hello, world!' consolelog result # True or false provideroutcome_servicesend_replace_result_with_url 5'https://google.com' consolelog result # True or false
Content Extension
The content extension is an extension supported by most LMS platforms. It provides LTI providers a way to send content back to the LMS in the form of urls, images, files, oembeds, iframes, and even lti launch urls.
provider = consumer_keyconsumer_secret providervalid_request req #check if the request is valid and if the content extension is loaded. if !is_valid || !providerext_content return false providerext_contenthas_return_type 'file' # Does the consumer support files providerext_contenthas_file_extension 'jpg' # Does the consumer support jpg # All send requests take a response object as the first parameter. How the # response object is manipulated can be overrided by replacing # lti.Extensions.Content.redirector with your own function that accepts two # parameters, the response object and the url to redirect to. providerext_contentsend_file resfile_urltextcontent_mime_type providerext_contentsend_iframe resiframe_urltitle_attributewidthheight providerext_contentsend_image_url resimage_urltextwidthheight providerext_contentsend_lti_launch_url reslaunch_urltitle_attributetext providerext_contentsend_oembed resoembed_urlendpoint providerext_contentsend_url reshyperlink_urltexttitle_attributetarget_attribute
Running Tests
To run the test suite first installing the dependencies:
npm install
make test