Hono middleware for LTI 1.3. Serverless-optimized with automatic route handling.
Create a new Hono app
npm create hono@latest
Install the packages
npm install @lti-tool/core @lti-tool/hono @lti-tool/memory
Create a minimal Hono powered LTI tool
import { Hono } from 'hono';
import { LTITool } from '@lti-tool/core';
import {
jwksRouteHandler,
launchRouteHandler,
loginRouteHandler,
secureLTISession,
} from '@lti-tool/hono';
import { MemoryStorage } from '@lti-tool/memory';
// Generate keypair (use proper key management in production)
const keyPair = await crypto.subtle.generateKey(
{
name: 'RSASSA-PKCS1-v1_5',
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: 'SHA-256',
},
true,
['sign', 'verify'],
);
const ltiConfig = {
stateSecret: new TextEncoder().encode('your-secret'),
keyPair,
storage: new MemoryStorage(),
};
const ltiTool = new LTITool(ltiConfig);
const app = new Hono();
// Add LTI routes
app.get('/lti/jwks', jwksRouteHandler(ltiConfig));
app.post('/lti/launch', launchRouteHandler(ltiConfig));
app.post('/lti/login', loginRouteHandler(ltiConfig));
// Protect routes with LTI session
app.use('/protected/*', secureLTISession(ltiConfig));
app.get('/protected/content', (c) => {
const session = c.get('ltiSession');
return c.json({ message: `Hello ${session.user.name}!` });
});
/login, /launch, /jwks endpointsIndividual route handlers for LTI endpoints. Each handler takes your LTI configuration.
Handles LTI login initiation (OIDC third-party initiated login).
import { loginRouteHandler } from '@lti-tool/hono';
app.post('/lti/login', loginRouteHandler(ltiConfig));
Handles LTI launch verification and session creation.
import { launchRouteHandler } from '@lti-tool/hono';
app.post('/lti/launch', launchRouteHandler(ltiConfig));
Serves the JSON Web Key Set (JWKS) for platform verification.
import { jwksRouteHandler } from '@lti-tool/hono';
app.get('/lti/jwks', jwksRouteHandler(ltiConfig));
Middleware to protect routes with LTI session validation.
import { secureLTISession } from '@lti-tool/hono';
app.use('/protected/*', secureLTISession(ltiTool.config));
app.get('/protected/grades', (c) => {
const session = c.get('ltiSession'); // Typed LTISession
// Handle authenticated request
});
The middleware extends Hono context with:
interface HonoLTIContext {
ltiSession: LTISession; // Available in protected routes
}
Optimized for serverless: