,

 LTI no es un plugin: es una frontera de producto

Publicado el

· Actualizado el

· Por

La arquitectura LTI no empieza cuando Moodle, Canvas u otro LMS envía un id_token. Empieza antes: cuando decides qué responsabilidades conserva la plataforma educativa y cuáles pertenecen a la herramienta externa. Esa decisión apenas se ve en una demostración, pero determina si estás construyendo un producto realmente desacoplado o un plugin distribuido que continúa dependiendo del LMS para casi todo.

Hacer funcionar un launch es la parte visible y, normalmente, la más sencilla. La complejidad aparece después, cuando hay que resolver identidad, tenants, roles, permisos, cursos copiados, selección de contenidos, roster, calificaciones, privacidad, rotación de claves y soporte para varias plataformas. Si esas decisiones se improvisan dentro de cada endpoint, la integración puede funcionar hoy y convertirse mañana en una fuente constante de deuda técnica.

Por eso conviene tratar LTI 1.3 como una frontera de producto y no solo como un mecanismo de acceso. En este artículo veremos cómo diseñar esa frontera, qué información debería cruzarla, cómo separar el protocolo del dominio y cuándo una arquitectura LTI aporta más valor que un plugin tradicional. El objetivo no es explicar únicamente cómo validar un token, sino cómo construir una integración que pueda mantenerse, observarse y evolucionar sin arrastrar las estructuras internas del LMS.

TL;DR

La arquitectura LTI no consiste solo en abrir una herramienta desde el LMS. Define una frontera de producto: establece qué sistema controla la identidad, el contexto, los datos, la seguridad y cada responsabilidad operativa.

  • LTI no debería entenderse únicamente como “abrir una URL desde Moodle”.
  • Una buena arquitectura LTI separa el contexto académico del dominio propio de la herramienta.
  • El launch es solo la puerta de entrada: detrás aparecen identidad, tenancy, autorización, datos, roster, contenido y calificaciones.
  • LTI 1.3 utiliza OpenID Connect, JWT, claves asimétricas y servicios OAuth 2.0; implementarlo bien exige algo más que validar una firma.
  • El LMS puede conservar cursos, matrículas, roles académicos y libro de calificaciones sin convertirse en el backend del producto externo.
  • La pregunta decisiva sigue siendo: qué responsabilidad pertenece al LMS y cuál pertenece al producto.

Una integración madura comparte contratos. No comparte las tripas de los sistemas.

Ilustración AMS Notebook: LTI no es un plugin: es una frontera de producto
LTI se vuelve mucho más interesante cuando lo utilizas para separar capacidades y no solo para lanzar una pantalla.

Desde fuera parece un enlace

El alumno entra en Moodle, pulsa una actividad y se abre una herramienta. Desde la interfaz, LTI puede parecer exactamente eso: un enlace con autenticación. Sin embargo, una arquitectura LTI empieza mucho antes de ese clic y continúa después del launch.

Pero debajo hay una pregunta arquitectónica bastante más importante:

¿Dónde termina el LMS y dónde empieza tu producto?

La respuesta condiciona el modelo de datos, la seguridad, el roadmap, el despliegue y hasta la forma de atender incidencias. Si no defines esa frontera, puedes terminar construyendo una aplicación externa que sigue dependiendo de Moodle para casi todo: usuarios, permisos, tablas, configuración y lógica de negocio. Para ver el contraste en un caso concreto, puedes consultar esta guía práctica de integración LTI con Moodle.

Entonces no has creado un producto desacoplado. Has movido una pantalla fuera del LMS.

Si respondes bien, en cambio, LTI se convierte en un contrato estable entre dos sistemas que conocen cosas distintas y evolucionan a ritmos distintos.

La visión mínima: LTI como launch

La implementación más básica suele imaginar este flujo:

Markdown
LMS

launch

Tool

Funciona y, para algunos casos, puede ser suficiente. El problema aparece cuando la herramienta empieza a necesitar algo más que saber quién ha pulsado el enlace:

  • identificar la institución que está entrando;
  • conocer el curso y el recurso concreto;
  • interpretar roles académicos;
  • seleccionar o crear contenido;
  • consultar participantes;
  • devolver calificaciones;
  • conservar configuración por placement;
  • soportar más de un LMS;
  • operar con distintas políticas de privacidad;
  • diagnosticar por qué falla un launch en un cliente y no en otro.

En ese momento, LTI deja de ser una pieza de SSO. A partir de ahí, la arquitectura LTI empieza a formar parte del diseño del producto.

Ilustración AMS Notebook: LTI como launch frente a frontera de producto
El launch inicia la experiencia. La frontera define qué información cruza, con qué garantías y qué sistema responde de cada capacidad.

Cómo funciona un launch en una arquitectura LTI

LTI 1.3 no envía simplemente un formulario con un usuario y un curso. El flujo se apoya en OpenID Connect y en mensajes firmados. De forma simplificada:

  1. El LMS inicia el login contra el endpoint de la herramienta.
  2. La herramienta genera y conserva state y nonce, y redirige al endpoint de autorización de la plataforma.
  3. El LMS autentica al usuario y devuelve un id_token mediante un POST al redirect_uri registrado.
  4. La herramienta valida la firma utilizando la JWKS de la plataforma.
  5. También valida emisor, audiencia, tiempos, nonce, deployment y tipo de mensaje.
  6. Solo después crea una sesión local o ejecuta el caso de uso correspondiente.

La especificación LTI 1.3 Core de 1EdTech define los mensajes y claims principales. En una implementación real conviene prestar atención, como mínimo, a:

  • iss, que identifica a la plataforma emisora;
  • aud y azp, que delimitan el cliente destinatario;
  • sub, que identifica al usuario dentro del contexto del emisor;
  • exp, iat y nonce, que ayudan a impedir reutilizaciones y mensajes fuera de ventana;
  • deployment_id, que identifica la instalación concreta de la herramienta;
  • message_type, que diferencia un resource link launch de un Deep Linking request;
  • context, resource_link y roles, que transportan contexto académico;
  • los claims de servicios, que anuncian endpoints y scopes disponibles para NRPS o AGS.

Un error habitual consiste en validar la firma y considerar que el trabajo ha terminado. La firma responde a “quién emitió este token y si fue alterado”. En cambio, no responde por sí sola a “si estaba destinado a esta instalación, si sigue vigente, si el nonce ya fue usado o si el deployment está activo”.

Registro, deployment y tenant no son lo mismo

Este punto es especialmente importante en productos SaaS.

En LTI 1.1 era frecuente asociar una integración a una consumer key y un secreto compartido. LTI 1.3 separa mejor el registro técnico de la herramienta y sus deployments. La propia guía de migración de 1EdTech propone identificar una integración mediante la combinación de issuer, client_id y deployment_id.

Por tanto, esa separación tiene consecuencias directas sobre el modelo multitenant de una arquitectura LTI:

Markdown
Platform registration
  └── issuer + client_id
        ├── deployment A → institución A
        ├── deployment B → institución B
        └── deployment C → institución C

No asumiría que client_id equivale siempre a un cliente de negocio. Tampoco usaría el dominio del LMS, el correo del usuario o el context_id para resolver el tenant. La frontera debería contar con un registro explícito de integraciones:

Markdown
LtiRegistration
- issuer
- client_id
- auth_login_url
- auth_token_url
- jwks_url
- status

LtiDeployment
- registration_id
- deployment_id
- tenant_id
- enabled_services
- privacy_policy
- status

Esto permite desactivar un deployment sin romper los demás, aplicar políticas por institución y conservar una trazabilidad clara. También prepara el producto para registro dinámico cuando la plataforma lo soporte. La especificación de Dynamic Registration automatiza parte del intercambio de configuración, pero no elimina la necesidad de gobernar qué institución, contrato y tenant representa cada deployment.

El LMS conoce el contexto. Tu producto conoce su dominio

Esta separación es una de las ideas más útiles de una buena arquitectura LTI.

El LMS puede ser owner deLa herramienta puede ser owner de
Matrículas y pertenencia al cursoActividad especializada
Contexto académicoDatos de dominio
Roles institucionalesReglas de negocio propias
Navegación generalExperiencia de usuario
Libro de calificacionesCálculo del resultado
Disponibilidad del recurso en el cursoConfiguración funcional
Políticas institucionalesRoadmap y ciclo de despliegue

La frontera no implica que cada dato viva en un solo sitio sin ninguna copia. Implica que existe un system of record claro y que las réplicas tienen una finalidad, una caducidad y una estrategia de reconciliación. Esta separación también es la base de una arquitectura Headless LMS que pueda evolucionar sin vaciar al LMS de su responsabilidad académica.

Por ejemplo, la herramienta puede necesitar conservar el nombre de un curso para mostrarlo en su panel. Eso no convierte su base de datos en la fuente oficial del catálogo académico. Del mismo modo, el LMS puede mostrar una calificación calculada por la herramienta sin apropiarse de la lógica que la produjo.

Ilustración AMS Notebook: Responsabilidades LMS vs herramienta
Una frontera clara evita que el producto externo se convierta en una extensión accidental de las tablas internas del LMS.

LTI Advantage: servicios, no magia

LTI 1.3 moderniza la relación de confianza. Además, LTI Advantage añade contratos para resolver necesidades habituales sin depender de una API propietaria de Moodle, Canvas o cualquier otra plataforma compatible. Dentro de una arquitectura LTI, estos servicios conectan capacidades sin mezclar los dominios de ambos sistemas.

Deep Linking: seleccionar antes de lanzar

Deep Linking 2.0 permite que el docente entre en la herramienta, seleccione o cree un recurso y lo devuelva al LMS como un elemento enlazado. No es únicamente un selector bonito: permite que la herramienta participe en la autoría y configuración sin obligar al LMS a conocer su catálogo interno.

El producto debería decidir qué configuración queda embebida en el enlace, cuál se guarda en su dominio y cómo versionar recursos que ya están utilizados en varios cursos.

NRPS: roster bajo demanda

Names and Role Provisioning Services permite consultar miembros y roles del contexto cuando la plataforma lo autoriza. Es útil para paneles docentes, actividades de grupo o procesos que necesitan conocer participantes antes de que todos hayan hecho launch.

Ahora bien, NRPS no obliga a replicar todo el roster en cada acceso. Conviene decidir si necesitas una consulta puntual, una caché temporal o una sincronización persistente. Cada opción cambia los requisitos de privacidad, borrado y consistencia.

AGS: resultados y line items

Assignment and Grade Services permite gestionar line items, publicar puntuaciones y consultar resultados. Es más expresivo que el antiguo Basic Outcomes y rompe la idea de que cada resource link solo puede asociarse a una columna simple.

En producto, la decisión importante no es solo “podemos enviar una nota”, sino:

  • quién calcula el resultado;
  • cuándo se considera definitivo;
  • si el envío es síncrono o mediante una cola;
  • cómo se reintenta sin duplicar efectos;
  • qué ocurre si el LMS rechaza la puntuación;
  • cómo se concilian cambios manuales en el libro de calificaciones.
Ilustración AMS Notebook: LTI 1.3: contexto y servicios
LTI Advantage mantiene la frontera sin renunciar a selección de contenidos, roster y calificaciones.

No uses el email como identidad

Otro error común consiste en convertir el email recibido en el identificador principal del usuario. Es tentador porque resulta legible y parece estable. En la práctica puede cambiar, no estar disponible o no ser único entre instituciones.

En una arquitectura LTI, la identidad externa debería tratarse como una asociación contextual. Un modelo razonable puede conservar:

Markdown
ExternalIdentity
- issuer
- client_id
- subject
- tenant_id
- local_user_id
- last_seen_at

El sub debe interpretarse dentro del emisor y del cliente correspondiente, no como un identificador universal. Nombre, email y avatar son atributos de perfil; no deberían ser la clave con la que relacionas progreso, permisos o facturación.

Además, este diseño ayuda a aplicar minimización de datos. Algunas herramientas necesitan nombre y correo. Otras pueden funcionar con un identificador opaco, rol y contexto. Cuantos más datos replicas, más superficie de sincronización, retención, privacidad y borrado introduces.

La integración debería transportar y conservar lo necesario, no todo lo disponible.

Los roles LTI no sustituyen tu autorización

Que el token incluya un rol de Instructor no significa que el usuario pueda ejecutar cualquier acción administrativa dentro de tu producto.

Los roles LTI describen la relación académica que comunica la plataforma. Tu herramienta sigue necesitando una política de autorización propia. Puede mapear roles externos a capacidades internas, pero ese mapeo debería ser explícito, configurable y verificable.

Por ejemplo:

Markdown
Instructor → ver panel del contexto, configurar actividad
Learner    → realizar actividad, consultar su resultado
Admin      → no se concede automáticamente por un rol genérico

Este matiz evita que una diferencia de roles entre Moodle y Canvas termine abriendo permisos inesperados. También permite introducir capacidades específicas del producto que no tienen equivalente académico.

Un producto LTI debería sobrevivir a otro LMS

Una prueba conceptual muy útil es preguntarse:

Si mañana el cliente cambia Moodle por Canvas, ¿qué parte de tu producto desaparece?

Si la respuesta es “casi toda”, quizá la frontera no está bien diseñada.

Una herramienta puede tener adaptadores específicos para peculiaridades de cada plataforma. Aun así, una arquitectura LTI sostenible no debería introducir esas diferencias dentro de su dominio:

PHP
$DB->get_record('course', ...);

El modelo deseable se parece más a este:

Markdown
Moodle ──┐
Canvas ──┼── Adaptador LTI ──► Casos de uso ──► Dominio
Otro LMS ┘

El adaptador valida el protocolo y traduce claims externos a comandos internos. La aplicación decide el caso de uso. El dominio trabaja con conceptos propios y no con URLs de claims, nombres de tablas de Moodle o particularidades del libro de calificaciones de Canvas.

Ilustración AMS Notebook: Producto desacoplado y multi-LMS
Cuando el contrato es la frontera, añadir otra plataforma es un trabajo de integración, no una reescritura del dominio.

Una arquitectura LTI que pueda mantenerse

Separaría al menos cinco capas o responsabilidades:

1. Registro de plataformas y deployments

Resuelve issuer, cliente, endpoints, JWKS, tenant, servicios habilitados y estado de la integración. No debería estar repartido entre variables de entorno y condicionales por cliente.

2. Adaptador de protocolo

Implementa login initiation, validación del launch, Deep Linking y obtención de tokens OAuth 2.0. Aquí viven state, nonce, JWT, JWKS, scopes y traducción de errores del protocolo.

3. Capa de aplicación

Convierte un launch válido en una intención: abrir una actividad, configurar un recurso, consultar un panel docente o continuar un intento.

4. Dominio del producto

Contiene actividad, progreso, evaluación, reglas y datos propios. No debería necesitar saber qué LMS originó la petición salvo que exista una regla de negocio real que lo justifique.

5. Adaptadores de salida

Encapsulan NRPS, AGS, webhooks internos, colas y observabilidad. Enviar una calificación no debería contaminar el modelo de dominio con detalles de OAuth o endpoints del LMS.

Como resultado, esta estructura actúa como una capa anticorrupción: el protocolo cambia en el borde; el producto conserva un lenguaje interno estable. Si quieres ampliar la perspectiva más allá del lanzamiento, en esta guía explico cómo encaja LTI dentro de la interoperabilidad educativa de un campus digital.

Seguridad: validar más que la firma

La Security Framework de 1EdTech define el uso de OpenID Connect, JWT, claves y OAuth 2.0 que acompaña a LTI 1.3. En una implementación de producción revisaría al menos:

  • state de un solo uso y vinculado al navegador que inició el flujo;
  • nonce persistido temporalmente y rechazado si se reutiliza;
  • comprobación estricta de iss, aud, azp, exp e iat;
  • algoritmo permitido explícitamente, normalmente RS256 en LTI 1.3;
  • selección de clave mediante kid y actualización controlada de JWKS;
  • validación de deployment_id contra un deployment activo;
  • allowlist de redirect y target link URIs;
  • separación entre sesión del producto y token recibido;
  • almacenamiento seguro de claves privadas;
  • rotación de claves publicando más de una clave durante la transición;
  • tokens OAuth de corta duración y limitados a los scopes necesarios;
  • logs sin tokens completos ni PII innecesaria.

Por último, trataría los iframes como una decisión de experiencia y seguridad, no como el comportamiento por defecto. Cookies SameSite, políticas CSP, navegadores restrictivos y bloqueos de terceros pueden hacer que una integración funcione en una pestaña y falle embebida.

La operación empieza después del launch

Un launch válido no garantiza que el producto sea operable. Las incidencias reales suelen requerir responder preguntas como:

  • ¿qué issuer y deployment originaron la petición?;
  • ¿qué kid se utilizó y cuándo se refrescó la JWKS?;
  • ¿falló la autenticación o la autorización interna?;
  • ¿el LMS ofreció el scope de AGS esperado?;
  • ¿una calificación está pendiente, enviada, rechazada o reintentándose?;
  • ¿el fallo afecta a una institución, a un curso o a todos los tenants?;

Por eso conviene asignar un correlation ID desde el login initiation y conservarlo durante launch, sesión, llamadas a servicios y jobs asíncronos. Además, las métricas deberían separar errores de protocolo, configuración, dependencia externa y dominio.

Para AGS utilizaría una cola con reintentos acotados, backoff y una clave de idempotencia funcional. El alumno no debería esperar a que el LMS confirme una calificación para ver completada su actividad. Primero se confirma el resultado en el producto; después se sincroniza y se hace visible su estado operativo.

Errores que convierten LTI en deuda técnica

Hay varios patrones que parecen acelerar la primera demo y encarecen todo lo que viene después:

Tratar el launch como un login genérico

Se pierde el resource link, el deployment, el contexto y la intención del mensaje. El usuario entra, pero el producto no sabe realmente a qué viene.

Crear usuarios y cursos sin una política de ciclo de vida

Cada launch duplica datos, pero nadie define actualización, retención, anonimización o borrado.

Usar email o context_id como tenant

Funciona en la primera instalación y colisiona cuando aparecen varios deployments, dominios o cursos regenerados.

Mezclar protocolo y dominio

Los casos de uso terminan recibiendo claims completos y comparando URIs de roles. Cualquier diferencia de plataforma se propaga por todo el código.

Enviar calificaciones dentro de la petición del alumno

La latencia y disponibilidad del LMS pasan a controlar la experiencia principal del producto.

No planificar rotación de claves

Todo funciona hasta que cambia un kid, caduca una clave o una plataforma mantiene temporalmente dos claves válidas.

Prometer “compatible con LTI 1.3” sin definir servicios

Core launch, Deep Linking, NRPS y AGS son capacidades distintas. La compatibilidad debería expresarse como una matriz verificable por plataforma y deployment.

Arquitectura LTI o plugin: una decisión contextual

No todo debería salir del LMS. Un plugin sigue siendo una opción excelente cuando la funcionalidad depende profundamente de APIs internas, es pequeña, solo existe para una instalación o puede compartir el ciclo de actualización de la plataforma. Tampoco conviene confundir LTI con una API de automatización: la API REST de Moodle resuelve otros contratos y puede coexistir con LTI.

PreguntaFavorece pluginFavorece producto LTI
¿Debe funcionar en varios LMS?No
¿Tiene dominio y datos propios?PocoMucho
¿Necesita desplegarse con frecuencia?No
¿Depende de eventos o tablas internas del LMS?MuchoPoco
¿Requiere escalado independiente?No
¿Tiene roadmap comercial propio?No
¿La experiencia debe vivir dentro del LMS?CompletamenteSolo como punto de entrada

La arquitectura LTI tiene sentido cuando existe una capacidad que merece una frontera propia. Si no existe esa independencia, externalizarla puede añadir autenticación, tenancy, observabilidad y operación sin obtener un beneficio real.

Cómo diseñar la frontera de una arquitectura LTI

Antes de escribir endpoints OIDC, documentaría estas decisiones:

Identidad

  • ¿Qué clave relaciona la identidad externa con el usuario local?
  • ¿Necesitamos nombre y email o basta un identificador opaco?
  • ¿Cómo se fusionan o separan identidades de varias plataformas?

Tenant y deployment

  • ¿Qué entidad de negocio representa cada deployment?
  • ¿Puede un tenant tener varios deployments?
  • ¿Cómo se desactiva una integración sin borrar su histórico?

Contexto y recurso

  • ¿Qué significa un curso dentro del producto?
  • ¿Qué configuración pertenece al resource link?
  • ¿Qué ocurre cuando un curso se copia o se restaura?

Roles y autorización

  • ¿Qué roles externos reconocemos?
  • ¿Qué capacidades internas concede cada uno?
  • ¿Qué acciones requieren permisos propios del producto?

Datos y privacidad

  • ¿Cuál es el system of record de cada dato?
  • ¿Qué información se replica y durante cuánto tiempo?
  • ¿Cómo se atienden borrado, retención y auditoría?

Calificaciones y roster

  • ¿La herramienta calcula y el LMS muestra?
  • ¿La sincronización es inmediata o asíncrona?
  • ¿Necesitamos roster completo, parcial o bajo demanda?

Operación

  • ¿Qué observamos por issuer, deployment y contexto?
  • ¿Cómo rotamos claves?
  • ¿Qué podemos reintentar y qué necesita intervención humana?
Ilustración AMS Notebook: Checklist para una frontera LTI
Una implementación sólida empieza decidiendo responsabilidades, identidad y operación antes de escribir el primer launch.

Un camino de implementación razonable

No intentaría construir todo LTI Advantage en la primera iteración. En su lugar, construiría la arquitectura LTI por capas:

  1. Core launch seguro: registro, deployment, validación completa, sesión y observabilidad.
  2. Modelo de dominio desacoplado: identidad externa, contexto y resource link traducidos a conceptos internos.
  3. Deep Linking: cuando el docente necesite seleccionar o configurar contenido desde el LMS.
  4. AGS: con colas, idempotencia, estados y reconciliación.
  5. NRPS: solo si el caso de uso necesita roster antes del launch individual.
  6. Multi-LMS real: pruebas de contrato y adaptadores para diferencias documentadas.
  7. Registro dinámico y certificación: cuando el volumen de instalaciones justifique automatizar onboarding y demostrar conformidad.

Este orden reduce el riesgo de construir servicios que el producto todavía no necesita y obliga a resolver primero la frontera que sostiene todo lo demás.

Veredicto

LTI no es un plugin. Tampoco es simplemente una URL con SSO. Es una decisión de arquitectura LTI que debe sostenerse cuando cambian el LMS, el volumen o las necesidades del producto.

Es un contrato entre una plataforma que posee contexto educativo y una herramienta que posee una capacidad especializada. Ese contrato incluye identidad, seguridad, deployments, servicios, ownership de datos y responsabilidades operativas.

Cuando diseñas bien esa frontera consigues menos acoplamiento, más portabilidad, mejor ownership, un roadmap independiente y soporte multi-LMS más realista. Cuando la diseñas mal, solo trasladas fuera del LMS una dependencia que sigue siendo estructural.

En definitiva, ahí está el verdadero valor de LTI: no en abrir una pantalla, sino en permitir que dos productos colaboren sin dejar de ser productos distintos.

Conclusión: diseña la frontera antes de escribir código

Si tienes una integración LTI, dibuja dos columnas: LMS y Tool. Coloca usuarios, roles, cursos, datos, actividad, configuración, evaluación, claves, tenancy, observabilidad y reporting.

Después marca tres cosas para cada elemento:

  1. quién es el owner;
  2. qué información cruza la frontera;
  3. qué ocurre cuando la sincronización falla.

Las responsabilidades sobre las que dudes son probablemente las que más merece la pena aclarar antes de seguir desarrollando. Si necesitas convertir esas decisiones en una hoja de ruta, puedes revisar mi servicio de consultoría de arquitectura para plataformas educativas.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Sobre mí

Soy Andrés Martínez Soto, CTO y consultor EdTech especializado en Moodle, LTI, IA educativa, arquitectura de plataformas e integración de sistemas educativos.

Ver perfil profesional

¿Necesitas ordenar tu ecosistema EdTech?

Te ayudo a revisar plataformas, LMS, integraciones, automatizaciones, datos e IA educativa con una visión técnica y pedagógica.

Buscar