LTI Advantage Concepts

Copy Markdown View Source

LTI 1.3 defines how learning platforms connect with external tools. Understanding these concepts will help you configure Ltix, implement your storage adapter, and debug launch issues. If you're already familiar with LTI 1.3, skip ahead to How Ltix fits in.

What is LTI?

Learning Tools Interoperability (LTI) connects learning platforms (like Canvas, Moodle, or Blackboard) with external tools (like a quiz engine, coding sandbox, or video player). When a student clicks a link in their course, the platform launches the tool with information about who the user is, what course they're in, and what role they have.

LTI 1.3 uses OpenID Connect (OIDC) for the launch flow and signed JWTs for the data payload.

Launch flow

An LTI launch is a three-step browser redirect.

sequenceDiagram
    participant P as Platform
    participant B as Browser
    participant T as Tool

    P->>B: User clicks LTI link
    B->>T: 1. POST /lti/login (iss, login_hint, target_link_uri)
    T->>B: 2. Redirect to platform auth endpoint (nonce, state)
    B->>P: Follow redirect
    P->>P: Authenticate user, build signed JWT
    P->>B: 3. POST /lti/launch (id_token, state)
    B->>T: Forward POST
    T->>T: Validate JWT, extract claims
    T->>B: Render launch
  1. Login initiation - the platform sends the tool a login request for a user who wants to launch. The tool doesn't have the user's identity yet. It just gets the platform's identity and a hint. Ltix handles this in handle_login/3.

  2. Authorization redirect - the tool sends the browser to the platform's auth endpoint with a nonce and state parameter. The platform authenticates the user and builds a signed JWT.

  3. Launch - the platform POSTs the signed JWT back to the tool. The tool validates the signature, checks the nonce, and extracts the launch data. Ltix handles this in handle_callback/3.

The state parameter (stored in the session between steps 1 and 3) provides CSRF protection. It proves the launch callback came from the same browser session that initiated the login.

Registrations

A registration is the information your tool has about a platform. It's created out-of-band when a platform administrator sets up your tool, typically through a configuration UI on both sides.

A registration contains the following fields.

FieldWhat it is
issuerThe platform's identity URL (e.g. https://canvas.instructure.com)
client_idYour tool's OAuth2 client ID on that platform
auth_endpointWhere to redirect users for authentication
jwks_uriWhere to fetch the platform's public keys
token_endpointWhere to request access tokens for service calls (optional)
audienceThe audience the platform expects in token requests, when it differs from the token endpoint (optional)

In Ltix, this is Ltix.Registration. Your Ltix.StorageAdapter looks up registrations by issuer and client_id, both during login initiation and again during launch validation.

Deployments

A deployment is a specific installation of your tool on a platform. One registration (platform + client_id) can have many deployments, for example a tool installed in three different departments of the same university.

A deployment has a single deployment_id assigned by the platform. It's immutable, case-sensitive, and guaranteed unique within the registration.

In Ltix, this is Ltix.Deployment. Your storage adapter looks up deployments during launch validation, after the JWT's deployment_id is extracted.

Launch claims

The signed JWT in step 3 contains claims, which are structured data about the launch. Ltix parses these into Ltix.LaunchClaims.

Claim groupExamplesStruct field
User identitysubject, name, emailclaims.subject, claims.name
Rolesinstructor, learner, TAclaims.roles (list of %Role{})
Contextcourse ID, title, labelclaims.context
Resource linklink ID, titleclaims.resource_link
Launch metadatamessage type, version, target URIclaims.message_type, claims.target_link_uri
Service endpointsgradebook, names & rolesclaims.ags_endpoint, claims.memberships_endpoint
Customanything the platform addsclaims.custom, claims.extensions

The full launch result is Ltix.LaunchContext, which contains the claims together with the matched registration and deployment.

Roles

Platforms send roles as URI strings. A user can have multiple roles simultaneously, for example an instructor in the course and a staff member at the institution.

Roles have three scopes.

  • Context - course-level (instructor, learner, TA, content developer)
  • Institution - org-level (faculty, student, staff, administrator)
  • System - platform-level (system admin, account admin)

Ltix parses role URIs into Ltix.LaunchClaims.Role structs and provides predicates like Role.instructor?/1 for authorization. See Working with Roles for details.

Nonces

A nonce is a one-time-use random string that prevents replay attacks. The flow is as follows.

  1. During login, Ltix generates a nonce tied to the login's state and registration
  2. The nonce is included in the authorization request to the platform
  3. The platform returns it in the signed JWT
  4. During launch validation, Ltix checks the nonce against the state and calls your adapter to record it as used

If someone intercepts a JWT and tries to replay it, the nonce check fails because it was already used.

How Ltix fits in

Ltix handles the protocol (OIDC redirects, JWT parsing, signature verification, claim validation). Your application handles the rest.

Ltix's jobYour app's job
Build the authorization redirectStore the OIDC state in the session
Validate the JWT signature and claimsLook up registrations and deployments
Parse roles, context, resource linksRecord used nonces
Return structured launch dataDecide what to do with the launch