Verified import paths — ran on the pinned version, not inferred.
ToolConfig
✓ import pylti1p3; ToolConfig = pylti1p3.ToolConfig
✗ from pylti1p3 import ToolConfig
This quickstart demonstrates how to configure the `ToolConfig` and process an incoming LTI 1.3 Message Launch. It uses mock objects for the web request to make it runnable without a full web framework. In a real application, you would integrate `ToolConfig` and `MessageLaunch` with your chosen framework (e.g., Flask, Django, FastAPI) and handle the actual HTTP request object. The `id_token` in the mock request must be a valid JWT signed by the LTI platform for successful validation.
import os
import json
from pylti1p3.tool_config import ToolConfig
from pylti1p3.message_launch import MessageLaunch
# Mock a minimal request object for demonstration
# In a real application, this would come from your web framework (e.g., Flask, Django)
class MockRequest:
def __init__(self, method='POST', headers=None, form=None, data=None):
self.method = method
self.headers = headers or {}
self.form = form or {}
self.data = data # raw body for content_type application/json, etc.
def get_json(self):
return json.loads(self.data) if self.data and 'application/json' in self.headers.get('Content-Type', '') else None
def get_param(self, key, default=None):
return self.form.get(key, default)
# 1. Configure the LTI Tool
# These values would typically come from environment variables, database, or a configuration file
iss = os.environ.get('LTI_ISS', 'https://example.com')
client_id = os.environ.get('LTI_CLIENT_ID', 'your-client-id')
jwks_url = os.environ.get('LTI_JWKS_URL', 'https://example.com/platform/.well-known/jwks.json')
auth_login_url = os.environ.get('LTI_AUTH_LOGIN_URL', 'https://example.com/platform/login_initiations')
auth_token_url = os.environ.get('LTI_AUTH_TOKEN_URL', 'https://example.com/platform/access_token')
deployment_id = os.environ.get('LTI_DEPLOYMENT_ID', '1') # Example deployment ID
# Your tool's private key (for signing messages sent *to* the platform)
# In a real app, this would be loaded from a file or secure store
private_key = os.environ.get('LTI_TOOL_PRIVATE_KEY', '-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----')
# Your tool's public key (to be registered with the platform)
# In a real app, this would be loaded from a file or secure store
public_key = os.environ.get('LTI_TOOL_PUBLIC_KEY', '-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----')
tool_config = ToolConfig({
'key_set_url': jwks_url,
'iss': iss,
'client_id': client_id,
'deployment_ids': [deployment_id],
'auth_login_url': auth_login_url,
'auth_token_url': auth_token_url,
'private_key': private_key,
'public_key': public_key
})
# 2. Simulate an LTI 1.3 Message Launch request
# This is a highly simplified mock. A real LTI launch involves a POST request
# with a 'id_token' parameter (a signed JWT) and possibly 'state' for CSRF protection.
# For a basic example, we'll just demonstrate setting up the MessageLaunch object.
# In a real scenario, the 'id_token' would be extracted from the incoming request's form data.
# Here, we'll use a placeholder JWT string that would normally be generated by the Platform.
# Note: This placeholder JWT will NOT be valid for actual verification.
# A valid JWT needs to be signed by the platform's private key and match the JWKS.
example_id_token = os.environ.get('LTI_EXAMPLE_ID_TOKEN', 'eyJhbGciOiJSUzI1NiIsImtpZCI6IkExMjMifQ.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwic3ViIjoiMTIzNDUifQ.S0meS1gnedT0ken')
mock_form_data = {
'id_token': example_id_token,
'state': 'a_random_state_string'
}
mock_request = MockRequest(method='POST', form=mock_form_data)
# 3. Process the LTI Message Launch
# The MessageLaunch object requires a 'request' (your web framework's request object)
# and the 'ToolConfig' you just created.
try:
message_launch = MessageLaunch(mock_request, tool_config)
is_valid_launch = message_launch.validate()
if is_valid_launch:
print("LTI 1.3 Message Launch validated successfully!")
launch_data = message_launch.get_launch_data()
print("Launch Data (Payload):\n", json.dumps(launch_data, indent=2))
# Example: Accessing specific claims
print("User ID:", message_launch.get_sub()) # 'sub' is the user ID
print("Context Title:", message_launch.get_context_title()) # Course title
# Access LTI 1.3 services (e.g., Assignment and Grades Service)
# This requires the launch to contain the appropriate service context and claims
# if message_launch.has_ags():
# print("Assignments and Grades Service available!")
# ags = message_launch.get_ags()
# # Example: Get line items
# # line_items = ags.get_lineitems()
# # print("Line items:", line_items)
else:
print("LTI 1.3 Message Launch validation failed.")
except Exception as e:
print(f"An error occurred during LTI launch processing: {e}")
# In a real app, handle authentication/authorization errors gracefully