Registry / auth-security / pylti1p3

pylti1p3

JSON →
library2.0.0pypypiunverified

pylti1p3 is a Python library implementing the LTI 1.3 Advantage Tool specification, enabling seamless integration with LTI 1.3 platforms. It handles OAuth 2.0, JWT validation, deep linking, and various LTI services. The current version is 2.0.0, with an active release cadence addressing new LTI features, bug fixes, and Python compatibility.

pip install pylti1p3
INSTALL
IMPORT
SIG · PYLTI1P3
P
pylti1p3
auth-securitypythonv2.0.0
Install
3.1s avg
Import
Disk
38MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v2.0.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.910 runs
installs and imports cleanly · install 0.0s · import 0.000s · 39.4MB
glibc
py 3.103.910 runs
installs and imports cleanly · install 3.1s · import 0.000s · 40MB
38MB installed
● package 38MB
Code
Verified usage

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
Debug
Known issues
breakingVersion 2.0.0 dropped support for Python 2.7 and 3.5. Applications running on these Python versions will break.
fix
Upgrade your Python environment to 3.6 or newer. Python 3.8+ is recommended for security and continued support.
affects: 2.0.0 and above
breakingIn version 1.12.0, the `AssignmentsGradesService.put_grade` and `AssignmentsGradesService.get_grades` methods no longer automatically create new line items if they don't exist. You must explicitly create line items before attempting to put grades or retrieve grades for them.
fix
Before calling `put_grade` or `get_grades`, ensure the line item exists. Use `ags.find_lineitem_by_resource_id()` or `ags.find_lineitem_by_resource_link_id()` to check, and if not found, use `ags.post_lineitem()` to create it.
affects: 1.12.0 and above
gotchaIncorrect configuration of `ToolConfig` parameters, especially `private_key` and `public_key`, `key_set_url`, `auth_login_url`, and `auth_token_url`, is a common source of LTI launch failures.
fix
Double-check that your `ToolConfig` reflects the exact values provided by the LTI platform, including correct URLs, client IDs, and ensuring that your private key is correctly formatted (PEM, including headers/footers) and matches the public key registered with the platform.
affects: All versions
Upgrade
Version history
2.0.0latest on PyPI · released Nov 20, 2022
Audit
Dependencies
PyJWTrequiredRequired for JWT (JSON Web Token) handling, used in LTI 1.3 security and message signing/verification.
requestsrequiredUsed for making HTTP requests to LTI platforms for services like Assignments and Grades, Names and Role Provisioning.
cryptographyrequiredProvides cryptographic primitives for secure operations, including key handling for JWT signing.
lxmlrequiredUsed for parsing XML, specifically for IMS Global's OneRoster and other XML-based LTI specifications if applicable.
Agent activity
18 hits · last 30 days
node
16
OpenAI (training)
1
Resources
pylti1p3 — pip install pylti1p3 · libregistry