### Quick Start Setup Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Example of setting up the LTIJS Provider with MongoDB, configuring routes, and registering a platform. ```APIDOC ## Quick start > Setting up Ltijs ```javascript const path = require('path') // Require Provider const lti = require('ltijs').Provider // Setup provider lti.setup('LTIKEY', // Key used to sign cookies and tokens { // Database configuration url: 'mongodb://localhost/database', connection: { user: 'user', pass: 'password' } }, { // Options appRoute: '/', loginRoute: '/login', // Optionally, specify some of the reserved routes cookies: { secure: false, // Set secure to true if the testing platform is in a different domain and https is being used sameSite: '' // Set sameSite to 'None' if the testing platform is in a different domain and https is being used }, devMode: true // Set DevMode to false if running in a production environment with https } ) // Set lti launch callback lti.onConnect((token, req, res) => { console.log(token) return res.send('It\'s alive!') }) const setup = async () => { // Deploy server and open connection to the database await lti.deploy({ port: 3000 }) // Specifying port. Defaults to 3000 // Register platform await lti.registerPlatform({ url: 'https://platform.url', name: 'Platform Name', clientId: 'TOOLCLIENTID', authenticationEndpoint: 'https://platform.url/auth', accesstokenEndpoint: 'https://platform.url/token', authConfig: { method: 'JWK_SET', key: 'https://platform.url/keyset' } }) } setup() ``` ``` -------------------------------- ### Initialize Provider with setup method Source: https://github.com/cvmcosta/ltijs/blob/master/docs/migration.md Replaces the previous constructor-based initialization with the setup method to support singleton behavior. ```javascript // Require Provider const Lti = require('ltijs').Provider // Setup provider using contructor const lti = new Lti('LTIKEY', // Key used to sign cookies and tokens { url: 'mongodb://localhost/database' }, // Database configuration { appUrl: '/', loginUrl: '/login' }) // Optionally, specify some of the reserved routes ``` ```javascript // Require Provider const lti = require('ltijs').Provider // Setup provider using setup method lti.setup('LTIKEY', // Key used to sign cookies and tokens { url: 'mongodb://localhost/database' }, // Database configuration { appRoute: '/', loginRoute: '/login' }) // Optionally, specify some of the reserved routes ``` -------------------------------- ### Installation Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Install the ltijs package using npm. ```APIDOC ## Installation ### Installing the package ```shell $ npm install ltijs ``` ``` -------------------------------- ### Provider.deploy(options) Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Starts listening to a given port for LTI requests and opens connection to the configured database. ```APIDOC ## async Provider.deploy(options) ### Description Starts listening to a given port for LTIĀ® requests and opens connection to the configured database. ### Parameters #### Request Body - **encryptionkey** (String) - Required - Secret used to sign cookies and encrypt data. - **database** (Object) - Required - Database configuration. - **url** (String) - Required - Database url (Ex: mongodb://localhost/applicationdb). - **connection** (Object) - Optional - MongoDB database connection options. - **connection.user** (String) - Optional - Database user for authentication. - **connection.pass** (String) - Optional - Database pass for authentication. - **debug** (Boolean) - Optional - If set to true, enables mongoose debug mode. Default: false. - **plugin** (Object) - Optional - If set, uses the given database plugin instead of the default MongoDB. - **options** (Object) - Optional - LTI Provider options. - **appRoute** (String) - Optional - Lti Provider main url. Default: '/'. - **loginRoute** (String) - Optional - Lti Provider login url. Default: '/login'. - **keysetRoute** (String) - Optional - Lti Provider public jwk keyset route. Default: '/keys'. - **dynRegRoute** (String) - Optional - Dynamic registration route. Default: '/register'. - **https** (Boolean) - Optional - Set this as true in development if you are not using any web server to redirect to your tool. Default: false. - **ssl** (Object) - Optional - SSL certificate and key to be used if https flag is enabled. - **ssl.key** (String) - Optional - SSL key. - **ssl.cert** (String) - Optional - SSL certificate. - **staticPath** (String) - Optional - The path for the static files your application might serve. - **cors** (Boolean) - Optional - If set to false, disables cors. Default: true. - **serverAddon** (Function) - Optional - Allows the execution of a method inside of the server contructor. - **cookies** (Object) - Optional - Cookie configuration. - **cookies.secure** (Boolean) - Optional - Cookie secure parameter. Default: false. - **cookies.sameSite** (String) - Optional - Cookie sameSite parameter. Default: Lax. - **tokenMaxAge** (String) - Optional - Sets the idToken max age allowed in seconds. Default: 10. - **devMode** (Boolean) - Optional - If true, does not require state and session cookies to be present. Default: false. - **ltiaas** (Boolean) - Optional - If set to true, disables the creation and validation of the session cookies. Default: false. - **dynReg** (Object) - Optional - Setup for the Dynamic Registration Service. - **dynReg.url** (String) - Required - Tool Provider main URL. - **dynReg.name** (String) - Required - Tool Provider name. - **dynReg.logo** (String) - Optional - Tool Provider logo. - **dynReg.description** (String) - Optional - Tool Provider description. - **dynReg.redirectUris** (Array) - Optional - Additional redirect URIs. - **dynReg.customParameters** (Object) - Optional - Custom parameters object. - **dynReg.autoActivate** (Boolean) - Optional - Platform auto activation flag. Default: false. ``` -------------------------------- ### Basic Members Route Example Source: https://github.com/cvmcosta/ltijs/blob/master/docs/namesandroles.md A basic example of an Express.js route to fetch and send all members of a context. Ensure 'res.locals.token' is populated. ```javascript // Members route lti.app.get('/members', async (req, res) => { const members = await lti.NamesAndRoles.getMembers(res.locals.token) // Gets context members res.send(members) }) ``` -------------------------------- ### Install ltijs Package Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Use npm to install the ltijs package. This is the first step to integrating LTI functionality into your project. ```shell $ npm install ltijs ``` -------------------------------- ### Example ContextToken Object Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md A sample JSON structure of a contexttoken object for a Moodle platform. ```json // Example contexttoken for a Moodle platform { "contextId": "http%3A%2F%2Flocalhost%2FmoodlewTtQU3zWHvVeCUf12_57", "path": "/", "user": "2", "roles": [ "http://purl.imsglobal.org/vocab/lis/v2/institution/person#Administrator", "http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor", "http://purl.imsglobal.org/vocab/lis/v2/system/person#Administrator" ], "targetLinkUri": "http://localhost:3000", "context": { "id": "2", "label": "course", "title": "Course", "type": [ "CourseSection" ] }, "resource": { "title": "Ltijs Demo", "id": "57" }, "custom": { "system_setting_url": "http://localhost/moodle/mod/lti/services.php/tool/1/custom", "context_setting_url": "http://localhost/moodle/mod/lti/services.php/CourseSection/2/bindings/tool/1/custom", "link_setting_url": "http://localhost/moodle/mod/lti/services.php/links/{link_id}/custom" }, "lis": { "person_sourcedid": "", "course_section_sourcedid": "" }, "endpoint": { "scope": [ "https://purl.imsglobal.org/spec/lti-ags/scope/lineitem", "https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly", "https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly", "https://purl.imsglobal.org/spec/lti-ags/scope/score" ], "lineitems": "http://localhost/moodle/mod/lti/services.php/2/lineitems?type_id=1", "lineitem": "http://localhost/moodle/mod/lti/services.php/2/lineitems/26/lineitem?type_id=1" }, "namesRoles": { "context_memberships_url": "http://localhost/moodle/mod/lti/services.php/CourseSection/2/bindings/1/memberships", "service_versions": [ "1.0", "2.0" ] }, "launchPresentation": { "locale": "en", "document_target": "iframe", "return_url": "http://localhost/moodle/mod/lti/return.php?course=2&launch_container=3&instanceid=57&sesskey=6b5H1MF8yp" }, "messageType": "LtiResourceLinkRequest", "version": "1.3.0" } ``` -------------------------------- ### Retrieve Platform in onConnect Source: https://github.com/cvmcosta/ltijs/blob/master/docs/migration.md Example of using the IdToken's issuer and clientId to retrieve a platform during an LTI launch. ```javascript lti.onConnect((token, request, response, next) => { const plat = await lti.getPlatform(token.iss, token.clientId) } ) ``` -------------------------------- ### Install ltijs Package Source: https://github.com/cvmcosta/ltijs/blob/master/README.md Use npm to install the ltijs package. This is the first step to integrating LTIĀ® 1.3 functionality into your web application. ```shell npm install ltijs ``` -------------------------------- ### Setup Dynamic Registration with Ltijs Provider Source: https://github.com/cvmcosta/ltijs/blob/master/docs/dynamicregistration.md Configure the Ltijs Provider to enable dynamic registration. This requires setting the 'dynRegRoute' and 'dynReg' options in the Provider.setup method. Ensure all required fields within 'dynReg' are provided. ```javascript const lti = require('ltijs').Provider lti.setup('LTIKEY', { url: 'mongodb://localhost/database', connection: { user: 'user', pass: 'password' } }, { appRoute: '/', loginRoute: '/login', cookies: { secure: false, sameSite: '' }, devMode: true, dynRegRoute: '/register', dynReg: { url: 'http://tool.example.com', name: 'Tool Provider', logo: 'http://tool.example.com/assets/logo.svg', description: 'Tool Description', redirectUris: ['http://tool.example.com/launch'], customParameters: { key: 'value' }, autoActivate: false } } ) ``` -------------------------------- ### IdToken Object Structure Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Example of the IdToken object containing platform and user information. ```javascript { "iss": "http://localhost/moodle", "clientId": "CLIENTID", "deploymentId": "1", "platformId": "60b1fce753c875193d71b611e895f03d" "platformInfo": { "product_family_code": "moodle", "version": "2020042400", "guid": "localhost", "name": "moodle", "description": "Local Moodle" }, "user": "2", "userInfo": { "given_name": "Admin", "family_name": "User", "name": "Admin User", "email": "local@moodle.com" } } ``` -------------------------------- ### LTIjs Redirection URI Strategy Example Source: https://github.com/cvmcosta/ltijs/blob/master/docs/redirectionuris.md Illustrates how LTIjs manages URL parameters during the LTI launch flow. It shows the received target_link_uri, how parameters are stored in the state, the cleaned redirect_uri, and the final reapplication of parameters. ```javascript https://tool.com?resource=123 ``` ```javascript { state: "12uy3g8asd7123vasdjhv123876asd", query: { resource: "123" } } ``` ```javascript https://tool.com ``` ```javascript https://tool.com?resource=123 ``` -------------------------------- ### Example Member Object Structure Source: https://github.com/cvmcosta/ltijs/blob/master/docs/namesandroles.md Illustrates the structure of a single member object returned by the getMembers method, including status, names, email, user ID, and roles. ```json { "id" : "https://lms.example.com/sections/2923/memberships", "context": { "id": "2923-abc", "label": "CPS 435", "title": "CPS 435 Learning Analytics", }, "members" : [ { "status" : "Active", "name": "Jane Q. Public", "picture" : "https://platform.example.edu/jane.jpg", "given_name" : "Jane", "family_name" : "Doe", "middle_name" : "Marie", "email": "jane@platform.example.edu", "user_id" : "0ae836b9-7fc9-4060-006f-27b2066ac545", "lis_person_sourcedid": "59254-6782-12ab", "roles": [ "http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor" ] } ] } ``` -------------------------------- ### Names and Roles standard response structure Source: https://github.com/cvmcosta/ltijs/blob/master/docs/namesandroles.md Example of the JSON structure returned by the getMembers method. ```javascript { "id" : "https://lms.example.com/sections/2923/memberships", "context": { "id": "2923-abc", "label": "CPS 435", "title": "CPS 435 Learning Analytics", }, "members" : [ { "status" : "Active", "name": "Jane Q. Public", "picture" : "https://platform.example.edu/jane.jpg", "given_name" : "Jane", "family_name" : "Doe", "middle_name" : "Marie", "email": "jane@platform.example.edu", "user_id" : "0ae836b9-7fc9-4060-006f-27b2066ac545", "lis_person_sourcedid": "59254-6782-12ab", "roles": [ "http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor" ] } ] } ``` -------------------------------- ### Setup LTIjs Provider with Dynamic Registration Source: https://context7.com/cvmcosta/ltijs/llms.txt Configure the LTIjs provider with dynamic registration enabled. This includes setting up the database connection and defining dynamic registration parameters such as the registration endpoint, tool details, and custom parameters. ```javascript const lti = require('ltijs').Provider // Setup with dynamic registration enabled lti.setup('LTIKEY', { url: 'mongodb://localhost/database' }, { dynRegRoute: '/register', dynReg: { url: 'https://tool.example.com', name: 'My Learning Tool', logo: 'https://tool.example.com/logo.png', description: 'An awesome learning tool', redirectUris: [ 'https://tool.example.com/', 'https://tool.example.com/launch' ], customParameters: { tool_id: 'my_tool', version: '1.0' }, autoActivate: false, // Require manual activation useDeepLinking: true } } ) ``` -------------------------------- ### Deploy Ltijs Provider - Standard and Serverless Source: https://context7.com/cvmcosta/ltijs/llms.txt Deploy the Ltijs Provider, either as a standard Express server on a specified port or in serverless mode to be used as middleware. Includes setup for graceful shutdown. ```javascript const lti = require('ltijs').Provider lti.setup('LTIKEY', { url: 'mongodb://localhost/database' }) // Standard deployment const setup = async () => { await lti.deploy({ port: 3000, silent: false }) console.log('LTI Provider running on port 3000') } setup() // Serverless mode - use as middleware const express = require('express') const app = express() const setupServerless = async () => { await lti.deploy({ serverless: true }) app.use('/lti', lti.app) // Mount Ltijs at /lti prefix app.listen(3000) } setupServerless() // Graceful shutdown process.on('SIGTERM', async () => { await lti.close({ silent: false }) process.exit(0) }) ``` -------------------------------- ### Deploy Ltijs Application Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Deploys the Ltijs application by establishing a database connection and starting the Express server. It can be configured with options for port, silent mode, and serverless deployment. ```APIDOC ## Deploy Ltijs Application ### Description Initiates the deployment of the Ltijs application, which includes connecting to the configured database and starting the Express server. This method can be customized with various options. ### Method `await lti.deploy([options])` ### Parameters #### Options Object - **port** (number) - Optional - The port for the Express server. Defaults to 3000. - **silent** (boolean) - Optional - Suppresses deployment messages if true. Defaults to false. - **serverless** (boolean) - Optional - If true, Ltijs will not start the Express server, allowing integration with other servers. Defaults to false. ### Request Example (Default) ```javascript await lti.deploy() ``` ### Request Example (Customized) ```javascript await lti.deploy({ port: 3030, silent: false }) ``` ### Serverless Deployment Example ```javascript const app = express() lti.setup('EXAMPLEKEY', { url: 'mongodb://localhost/database' }) // Start LTI provider in serverless mode await lti.deploy({ serverless: true }) // Mount Ltijs express app into preexisting express app with /lti prefix app.use('/lti', lti.app) ``` ``` -------------------------------- ### Deploy Ltijs Application Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Deploys the Ltijs application, establishing a database connection and starting the Express server. Options include port, silent mode, and serverless deployment. ```javascript await lti.deploy() ``` ```javascript await lti.deploy({ port: 3030, silent: false }) ``` -------------------------------- ### lti.setup() Configuration Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md Configures the LTI provider with encryption key, database settings, and options. ```APIDOC ## POST /setup ### Description Sets up the LTI provider configuration. ### Method POST ### Endpoint /setup ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **encryptionKey** (String) - Required. Secret key for signing cookies and encrypting sensitive data. - **database** (Object) - Required. Database configuration. - **url** (String) - Required. Database connection URL. - **connection** (Object) - Optional. MongoDB Driver connection options (e.g., user, pass). - **debug** (Boolean) - Optional. Enables Mongoose's debug mode. - **plugin** (Object) - Optional. Database plugin (e.g., ltijs-sequelize). - **options** (Object) - Optional. Additional provider configuration. - **appRoute** (String) - Optional. Route for successful launch requests. Default: '/'. - **loginRoute** (String) - Optional. Route for OIDC login flow. Default: '/login'. - **keysetRoute** (String) - Optional. Route to serve JWK keyset. Default: '/keys'. - **dynRegRoute** (String) - Optional. Route for Dynamic Registration requests. Default: '/register'. - **cookies** (Object) - Optional. Cookie configuration. - **secure** (Boolean) - Optional. If true, cookies are only sent through https. Default: false. - **sameSite** (String) - Optional. Determines if cookie can be sent cross domain. Default: 'Lax'. - **domain** (String) - Optional. Cookie domain. ### Request Example ```json { "encryptionKey": "EXAMPLEKEY", "database": { "url": "mongodb://localhost/database", "connection": { "user": "user", "pass": "pass" } }, "options": { "appRoute": "/app", "loginRoute": "/loginroute", "keysetRoute": "/keyset", "dynRegRoute": "/register", "cookies": { "secure": true, "sameSite": "None", "domain": ".domain.com" } } } ``` ### Response #### Success Response (200) None (Setup is performed) #### Response Example None ``` -------------------------------- ### Configure Ltijs in main application file Source: https://github.com/cvmcosta/ltijs/blob/master/docs/migration.md Demonstrates initializing the singleton provider and deploying the application in a primary entry file. ```javascript // a.js // Require Provider const lti = require('ltijs').Provider // Require b.js const routes = require('./b') // Setup method can be called only once lti.setup('LTIKEY', { url: 'mongodb://localhost/database' }, { appRoute: '/', loginRoute: '/login' }) // Setting up routes lti.app.use(routes) lti.deploy() ``` -------------------------------- ### Configuring the Ltijs Provider Source: https://github.com/cvmcosta/ltijs/blob/master/docs/provider.md The lti.setup() method is required to initialize the provider with an encryption key, database connection, and optional configuration settings. ```javascript // Require Ltijs package const lti = require('ltijs').Provider // Setup provider example lti.setup('EXAMPLEKEY', { url: 'mongodb://localhost/database',// Database url connection:{ user:'user', pass: 'pass'}// Database configuration }, { appRoute: '/app',// Scpecifying main app route loginRoute: '/login', // Specifying login route cookies: { secure: true, // Cookies will only be passed through https. sameSite: 'None' // Cookies can be set across domains. } }) ``` ```javascript // Setup provider example lti.setup('EXAMPLEKEY', { url: 'mongodb://localhost/database',// Database url connection:{ user:'user', pass: 'pass'}// Database configuration }, { appRoute: '/app',// Scpecifying main app route loginRoute: '/loginroute', // Specifying login route keysetRoute: '/keyset', // Specifying keyset route dynRegRoute: '/register' // Specifying Dynamic registration route }) ``` ```javascript // Setup provider example lti.setup('EXAMPLEKEY', { url: 'mongodb://localhost/database',// Database url connection:{ user:'user', pass: 'pass'}// Database configuration }, { cookies: { // Cookie configuration secure: true, sameSite: 'None', domain: '.domain.com' } }) ``` -------------------------------- ### Implement a full LTI 1.3 provider application Source: https://context7.com/cvmcosta/ltijs/llms.txt This script initializes the LTI provider, handles standard and deep linking launches, manages course data, and performs grade submissions. Ensure the database connection string and encryption keys are configured correctly for your environment. ```javascript const lti = require('ltijs').Provider const path = require('path') // Setup lti.setup('MY_ENCRYPTION_KEY', { url: 'mongodb://localhost/lti_app' }, { cookies: { secure: true, sameSite: 'None' }, dynReg: { url: 'https://tool.example.com', name: 'Complete LTI Tool', logo: 'https://tool.example.com/logo.png', description: 'Full-featured LTI 1.3 tool', autoActivate: false } } ) // Whitelist public routes lti.whitelist('/health', '/public') // Main launch lti.onConnect(async (token, req, res) => { const context = token.platformContext return res.send(`
Course: ${context.context?.title || 'Unknown'}
Role: ${context.roles?.join(', ')}
Go to Dashboard `) }) // Deep linking launch lti.onDeepLinking(async (token, req, res) => { return lti.redirect(res, '/select-content') }) // Dashboard with grades and members lti.app.get('/dashboard', async (req, res) => { const token = res.locals.token try { // Get course members const membersResponse = await lti.NamesAndRoles.getMembers(token) // Get line items const lineItemsResponse = await lti.Grade.getLineItems(token) return res.json({ user: token.userInfo, course: token.platformContext.context, members: membersResponse.members, lineItems: lineItemsResponse.lineItems }) } catch (err) { return res.status(500).json({ error: err.message }) } }) // Content selection for deep linking lti.app.get('/select-content', async (req, res) => { return res.send(`