LTI 1.3 en producción: una frontera de confianza
Cómo separar registro, lanzamiento, identidad y servicios para que una integración pueda rechazarse, diagnosticarse y operarse con criterio.

LTI 1.3 permite que un LMS abra una herramienta externa con contexto académico y que ambos sistemas colaboren sin compartir contraseñas. Esa definición es correcta y se queda corta para producción. La integración solo resulta defendible cuando el equipo separa cuatro contratos: quién registra a quién, qué debe validar en cada lanzamiento, cómo identifica a personas y despliegues, y a qué servicios puede acceder después. Si esos cuatro ámbitos acaban dentro de un único controlador que "valida el JWT", la demo puede funcionar mientras la arquitectura ya ha empezado a fallar.
Mi recomendación es dibujar primero la frontera de confianza y escribir sus rechazos. El recorrido favorable viene después. Una herramienta LTI debe aceptar únicamente los lanzamientos que corresponden a un registro conocido, a un despliegue autorizado y a un mensaje íntegro. Este criterio cambia el modelo de datos, las pruebas, los registros y hasta la conversación de compra con el proveedor.
LTI 1.3 empieza antes del primer clic
El estándar conecta dos partes con nombres precisos. La plataforma suele ser Moodle, Canvas, Sakai u otro LMS, y la herramienta, una aplicación externa como un simulador, una evaluación, un laboratorio, un catálogo de contenidos o un producto propio. El navegador del estudiante participa en el lanzamiento, pero no establece por sí solo la confianza entre ambas.
La confianza empieza en el registro, donde la herramienta conoce el emisor de la plataforma, sus puntos de autorización, su dirección de claves públicas y el identificador de cliente asignado. A su vez, la plataforma conoce las direcciones de inicio y retorno de la herramienta, además de sus claves para los mensajes que viajan en sentido contrario. A ese registro se vinculan uno o varios despliegues, que representan instalaciones concretas de la integración.
Este matiz evita un error caro: usar el dominio del LMS como identificador del cliente. Una misma plataforma puede alojar varias instituciones, y una misma institución puede tener varios despliegues de una herramienta con permisos o ciclos de vida distintos. El issuer indica quién emite y el client_id identifica el registro de la herramienta. Por su parte, el deployment_id identifica la instalación autorizada dentro de ese acuerdo. Los tres cumplen funciones distintas.
La robustez depende de rechazar todo mensaje que no corresponda a un registro conocido, un despliegue autorizado y una prueba íntegra.
Dibuja primero quién confía en quién
Yo modelaría la configuración en dos niveles. El primero, casi inmutable, contiene el registro de la plataforma: emisor, puntos OIDC y OAuth, dirección JWKS, identificador de cliente y algoritmos admitidos. El segundo contiene cada despliegue: deployment_id, institución propietaria, estado, capacidades habilitadas, política de datos y fechas de activación o retirada.
Separarlos permite responder preguntas que una tabla única de configuración oculta. ¿Quién puede retirar un despliegue sin romper los demás? ¿Qué institución aceptó compartir correo y nombre? ¿Qué servicios están habilitados para este cliente? ¿Qué clave se usó para validar el lanzamiento? ¿Qué debe ocurrir al copiar un curso o migrar desde LTI 1.1?
El modelo también necesita conservar el historial. No propongo guardar secretos antiguos, sino poder explicar qué configuración estaba vigente cuando ocurrió un lanzamiento. Una incidencia investigada dos semanas después pierde valor si el registro solo muestra el estado actual y nadie sabe que la plataforma cambió el emisor, añadió una clave o sustituyó el identificador de despliegue.
El lanzamiento contiene dos recorridos
Un lanzamiento LTI 1.3 usa OpenID Connect, pero no empieza con un formulario de usuario en la herramienta. La plataforma envía primero una petición de inicio de sesión a una dirección registrada. Esa petición inicial no autentica a la plataforma: la herramienta utiliza sus parámetros solo para seleccionar por coincidencia exacta un registro conocido, genera state y nonce y redirige al punto de autorización registrado. La confianza no se establece hasta validar el id_token firmado que la plataforma devuelve, normalmente mediante un form_post del navegador a una dirección de retorno exacta.
"El token es válido" tampoco es una prueba suficiente. La herramienta debe validar la firma con la clave asociada al kid y con un algoritmo admitido para ese registro. En el ID token comprueba iss, aud, exp, la presencia y el formato de iat, y que el claim nonce coincida exactamente con el valor de un solo uso guardado al iniciar el recorrido. Por separado, compara el parámetro state de la respuesta OIDC con el valor exacto asociado a esa misma sesión y lo invalida después de usarlo. Si ha definido una ventana de frescura, rechaza además los iat que queden fuera de ella. Cuando la audiencia contiene varios valores, también comprueba el cliente autorizado que declara azp. Por último valida los campos propios de LTI (claims): versión, tipo de mensaje, despliegue y, cuando corresponde, recurso y curso. Un token firmado por una plataforma conocida puede seguir siendo inaceptable si iba dirigido a otro cliente o cita un despliegue retirado.
El target_link_uri de la primera petición merece el mismo cuidado. Sirve para iniciar el recorrido, pero llega antes del mensaje firmado. La decisión final sobre qué recurso mostrar debe apoyarse en el campo firmado del lanzamiento y en destinos previamente autorizados. Convertir cualquier dirección recibida en una redirección interna deja una puerta que el protocolo no tenía por qué abrir.
Aquí distinguiría tres resultados en lugar de un booleano:
| Resultado | Qué significa | Qué hace la herramienta |
|---|---|---|
| Rechazo de protocolo | Falta una prueba criptográfica o un campo obligatorio | No crea sesión y registra el motivo sin volcar datos personales |
| Rechazo de política | El mensaje es íntegro, pero el despliegue, recurso o rol no está autorizado | Devuelve una respuesta comprensible y conserva una traza de decisión |
| Lanzamiento aceptado | Protocolo y política coinciden | Crea una sesión local corta y pasa al dominio de la herramienta |
Esta separación mejora el diagnóstico y evita que un equipo "arregle" un problema de permisos relajando la validación criptográfica porque ambos terminaban en el mismo error genérico.
La identidad no cabe en un user_id
LTI 1.3 usa sub para identificar al sujeto, aunque no se trata de un identificador universal del alumno. La herramienta identifica a la persona mediante la pareja (iss, sub). Conserva client_id y deployment_id como datos del registro y de la instalación, sin incorporarlos automáticamente a la clave de persona. A partir de ahí, el despliegue indica a qué instalación institucional pertenece el acceso, y el curso o la organización sitúan la acción. Los roles describen la posición declarada en ese ámbito, sin sustituir la matriz de permisos de la aplicación.
| Pregunta | Identificadores que intervienen | Decisión propia de la herramienta |
|---|---|---|
| ¿Qué plataforma emitió? | iss | Registro de confianza aplicable |
| ¿Para qué herramienta? | aud / client_id | Cliente esperado y retorno permitido |
| ¿Qué instalación? | deployment_id | Institución, estado y política de datos |
| ¿Qué persona? | sub dentro del emisor (iss) | Cuenta interna o vínculo con una existente |
| ¿En qué ámbito? | context.id | Curso, organización o espacio de trabajo |
| ¿Con qué posición? | roles | Permisos locales mínimos que se conceden |
Yo no concedería permisos administrativos porque un texto de rol contiene una palabra reconocible. Normalizaría los roles admitidos, aplicaría una tabla explícita y empezaría por el conjunto mínimo. Los roles desconocidos son normales en ecosistemas extensibles; el comportamiento seguro es conservarlos para diagnóstico y no elevar privilegios.
También separaría identificación de datos de perfil. Nombre y correo pueden ser útiles para una experiencia concreta, pero no son necesarios para demostrar que el mensaje procede de la plataforma. La propia certificación contempla lanzamientos sin información personal identificable. Si la herramienta necesita correo para unir cuentas, esa necesidad debe aparecer como decisión de producto y privacidad, no camuflada como requisito técnico de LTI.
LTI Advantage abre otro contrato
El lanzamiento entrega un mensaje al navegador, pero AGS y NRPS funcionan entre servidores y utilizan otro mecanismo. Para acceder a estos servicios de LTI Advantage, la herramienta presenta una aserción firmada y obtiene un access_token con alcances concretos. Ese token permite llamar a los puntos de servicio que la plataforma ha anunciado para el curso.
Esta diferencia corrige dos ideas frecuentes: el id_token no debe enviarse después a AGS o NRPS, y haber recibido un lanzamiento tampoco concede acceso general al LMS. Cada servicio tiene direcciones, alcances y recursos propios.
LTI Advantage reúne tres capacidades principales:
- Deep Linking permite que un docente elija contenido en la herramienta y lo inserte en el curso como recursos concretos. Es un intercambio de mensajes, no una API de catálogo desligada del curso de origen.
- AGS permite gestionar elementos del libro de calificaciones y publicar resultados asociados. Su dificultad real aparece en los reintentos, los estados y la relación entre actividad, intento y línea de calificación.
- NRPS permite consultar nombres y roles de los miembros de un curso. Que exista no significa que toda herramienta necesite descargar la lista completa del aula.
El contrato de servicio debería registrar el alcance solicitado, el concedido, el punto anunciado por la plataforma y el recurso que justifica la llamada. Guardar solo un token hasta que caduque impide explicar por qué una operación estaba autorizada.
La privacidad se decide antes de asignar permisos a los roles
LTI reduce las integraciones a medida, pero no decide qué datos debe recibir una herramienta. Esa responsabilidad sigue en la institución y en el producto. Un simulador que solo devuelve una nota puede operar con un identificador seudónimo y la actividad. Una herramienta de colaboración quizá necesite nombres visibles, mientras que un sistema de soporte puede requerir el correo. Cada caso exige una decisión distinta.
La pregunta de privacidad útil En lugar de preguntar "¿enviamos datos personales por LTI?", preguntaría qué función visible deja de funcionar si retiramos cada dato. Si nadie puede señalarla, el dato no cruza la frontera. Después se documentan retención, borrado, soporte y subencargados con el mismo detalle que los endpoints.
NRPS merece una revisión aparte porque cambia la escala. El lanzamiento describe a quien está usando la herramienta. La lista de participantes puede exponer un conjunto de personas que nunca la han abierto. Antes de activarla, producto, seguridad y el responsable académico deberían acordar el caso de uso, la frecuencia, los campos, la retención y quién ve qué dentro de la herramienta.
La política de roles también debe respetar esa minimización. Un docente puede necesitar crear un recurso mediante Deep Linking sin tener acceso a todos los datos analíticos. Un administrador de plataforma no tiene por qué convertirse en administrador funcional de cada proveedor. LTI comunica la situación académica; la aplicación sigue siendo responsable de aplicar autorización de dominio.
Lo que suele romperse aparece después de integrar
Las demostraciones suelen limitarse al recorrido favorable: un registro, una clave, un curso y un navegador. Al llegar a producción aparecen la rotación, las copias de curso, los despliegues múltiples y los marcos integrados. También surgen bloqueos de almacenamiento, reintentos y proveedores que interpretan una parte opcional de forma distinta. Más que memorizar una lista de peculiaridades, hay que relacionar cada riesgo con una prueba y una señal.
| Riesgo | Prueba antes de abrir | Señal que debe quedar |
|---|---|---|
kid nuevo durante una rotación | Firmar con una clave ausente de caché y comprobar que se recarga JWKS | Recarga, emisor, kid, huella RFC 7638 de la clave pública, versión de configuración y resultado; nunca la clave privada |
| Repetición del lanzamiento | Repetir el mismo nonce y estado | Rechazo diferenciado de un token caducado |
| Emisor o audiencia inesperados | Cambiar cada campo del token por separado con firma válida | Motivo de rechazo y registro seleccionado |
| Despliegue retirado | Lanzar desde una instalación deshabilitada | Rechazo de política, no error criptográfico |
| Herramienta dentro de iframe | Probar navegadores con restricciones de almacenamiento | Modo de apertura, fallo de sesión y alternativa ofrecida |
| Servicio temporalmente caído | Forzar un tiempo de espera agotado y una respuesta de error | Cola, intento, operación de dominio e idempotencia |
| Curso copiado o restaurado | Copiar un recurso y volver a lanzarlo | Relación entre recurso anterior, nuevo y despliegue |
No fijaría en una guía estable que JWKS deba mantenerse en caché un número universal de horas ni que toda llamada tenga el mismo tiempo de espera. El contrato correcto es otro: respetar la política HTTP cuando exista, recargar ante un kid desconocido de un emisor fiable, limitar la espera según el camino del usuario y evitar que una indisponibilidad de AGS bloquee la pantalla del estudiante.
La observabilidad debe seguir el recorrido completo sin convertir datos educativos en etiquetas de alta cardinalidad. Un identificador de correlación puede unir inicio OIDC, retorno, sesión local y trabajo asíncrono. Los identificadores de estudiante, correo, nombre o respuesta no deberían acabar como atributos de métricas. Para investigar un caso concreto se usan registros protegidos y con retención definida, no etiquetas que se replican por todo el sistema de monitorización.
Una arquitectura que se pueda operar
La arquitectura que yo elegiría tiene cinco responsabilidades visibles:
- Un registro de plataformas y despliegues versionado, con propietarios y estado.
- Una entrada LTI que resuelve el registro, valida el protocolo y produce un objeto interno pequeño y tipado.
- Un servicio de identidad y autorización que relaciona sujeto, curso y roles sin contaminar el dominio con los campos originales del token.
- El dominio de la herramienta, que recibe una persona, una actividad y unos permisos; no un JWT de dos páginas.
- Adaptadores de LTI Advantage que firman o validan mensajes y, cuando corresponde, obtienen tokens y ejecutan operaciones remotas con reintentos e idempotencia.
Esa separación permite probar cada frontera con defectos concretos, sin responder a una búsqueda de pureza académica. Así se puede verificar que un aud incorrecto se rechaza sin arrancar el motor de evaluación. También permite simular un AGS caído sin repetir la entrega del alumno o cambiar la asignación de roles de una institución sin tocar el código que calcula una puntuación.
También permite degradar con criterio. Si NRPS no responde, quizá el docente no pueda abrir la vista de grupo, pero el estudiante puede seguir trabajando. Si AGS está caído, la herramienta conserva el resultado y lo publica después. Si no se puede validar la firma del lanzamiento, no existe una degradación segura: se rechaza. La arquitectura expresa esas diferencias en lugar de convertir cualquier dependencia caída en un error 500.
Lo que LTI 1.3 no resuelve
LTI 1.3 no sustituye a todas las APIs, no convierte una herramienta en pedagógicamente útil y no garantiza que dos productos certificados cubran las mismas capacidades opcionales. Tampoco decide quién es dueño de cada dato, cuánto se conserva, cómo se atiende una reclamación o qué ocurre cuando termina el contrato con el proveedor.
Para mover procesos de dominio que el estándar no define seguirá haciendo falta una API o un flujo de eventos. Para registrar experiencias de aprendizaje más allá del lanzamiento y la calificación puede encajar xAPI. La elección completa está en LTI 1.3, API o xAPI: cómo elegir la frontera correcta. La rotación, las trazas y la guía de operación necesitan una pieza propia.
La prueba final consiste en poder contestar, con datos y sin reconstruir el sistema de memoria, qué plataforma emitió el mensaje, por qué se aceptó, a qué despliegue pertenecía, qué datos cruzaron, qué permiso se concedió y qué ocurrió después con cada llamada. Cuando esas respuestas existen, LTI deja de ser un cable entre dos pantallas y se convierte en una frontera que el equipo puede gobernar.
Última revisión: 27 de julio de 2026.
Alberto Lara Hernández trabaja en dirección técnica, arquitectura de plataformas de aprendizaje e IA aplicada con gobierno. Publica análisis para equipos que necesitan tomar decisiones tecnológicas que sigan siendo explicables cuando el sistema crece.
Más de 22 años construyendo y evolucionando plataformas de aprendizaje que tienen que operar de verdad.
Seguir leyendo
- MCP y Moodle: arquitectura segura para agentes
Cómo situar una pasarela MCP delante de Moodle sin compartir tokens, exponer toda la API ni permitir que el contenido del curso gobierne las acciones del agente.
- NRPS y privacidad del aula: cuándo no pedir la lista de participantes
El servicio de participantes de LTI 1.3 garantiza dos campos: identificador y rol. Todo lo demás depende de un acuerdo entre plataforma y herramienta. Una integración que se rompe sin nombre o correo no tiene un problema de configuración: tiene un defecto de diseño.
- Operar LTI 1.3: rotación de claves, trazas y fallos explicables
Guía operativa de LTI 1.3 con fases observables, rotación de JWKS, trazas seguras, reintentos, pruebas negativas y respuesta a incidentes.


