LTI Launch Authentication with Node.js

3.8k views Asked by At

I have created a simple 'hello-world' web app using express.js framework.

I want the app to be IMS-LTI Compliant so that moodle and other Learning Management Systems can launch it as an external tool.

However, I do not understand how to authenticate the LTI launch in my app (it uses oauth), and I cannot find any express.js/node.js examples of how it's done either. I see that a passport-lti node module exists (https://www.npmjs.org/package/passport-lti), but as a noob with node I just don't understand the sparse documentation.

I have used passport.js to create local authentication - using this video (https://www.youtube.com/watch?v=twav6O53zIQ), I was hoping for similar help for the LTI launch authentication...

Any help is appreciated.

Cheers, Ollie

2

There are 2 answers

0
pfranza On BEST ANSWER

When an LTI Tool Consumer (i.e. an LMS) launches an LTI Application (Tool Provider) The LTI Tool is sent an HTTP Post.

In order to authenticate that the post is legitimate, you need to verify that the post variable 'oauth_signature' is valid by recomputing the signature locally using the shared secret key that you exchanged with the Tool Consumer when the LTI tool was configured.

The act of verifying the OAuth signature is likely handled by an OAuth library .. nodejs already has these, so please don't reimplement one.

You can read the full process of validating the launch request in the IMS Global documentation

5
rjerue On

Just wanted to mention that I ended up doing a working example of this awhile back.

https://github.com/ripples/Present/blob/master/server/app.js#L35

passport.use('lti-strategy', new CustomStrategy(
    function(req, callback) {
        var val = (req.body) ? req.body : req.user      
        try{
            var provider = new lti.Provider(val , process.env.LTI_SECRET)   
            if(req.user){
                callback(null, val)         
            }
            else{
                provider.valid_request(req, function(err, isValid) {
                    if(err){
                        console.log("LTI Error", err, isValid)
                    }
                    callback(err, val)
                });
            }       
        }
        catch(err){
            console.log("Authenication error", err)
            callback(err, null)
        }
    }
))

I ended up doing a custom passport strategy and using another library to do the authentication.

https://github.com/omsmith/ims-lti

It's that new lti.Provider bit, the key is that it takes in the LTI post req object to do auth.