1
0
Files
coldcall_lti/docs/SALTIRE.md
Benjamin Mako Hill 921f5d1c8a Add cookie-check template and saltire testing documentation
The real-handshake test against the saltire LTI platform emulator
turned up a launch bug dev mode cannot reach: pylti1p3's Flask adapter
requires the application to supply the cookies_allowed_js_check.html
template used by enable_check_cookies(), and without it every OIDC
login 500s. The template tests whether cookies survive, then re-enters
the login flow or offers a new-window fallback.

docs/SALTIRE.md records the verified test setup: local HTTPS with a
self-signed certificate, the platform description for
instance/lti_config.json, the saltire-side configuration, and the
session-id caveat on saltire's token/jwks URLs. The 2026-08-01 run
verified the full OIDC handshake, JWT validation, NRPS roster sync
over the wire, and instructor/learner role routing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 18:53:53 -07:00

86 lines
3.6 KiB
Markdown

# Testing against the saltire LTI platform emulator
[saltire](https://saltire.lti.app) is the ceLTIc project's hosted LTI
test harness. Its Platform Emulator impersonates an LMS: it performs
the real OIDC handshake, signs a real id_token, and answers NRPS
requests, which makes it the way to exercise the app's actual launch
path without a Canvas Developer Key. This setup was first run and
verified on 2026-08-01 (launch, role routing for both Instructor and
Learner, and a live NRPS roster sync all worked).
## Local side
The app must be served over HTTPS, because real LTI session cookies
are `Secure; SameSite=None`. A self-signed certificate is fine — you
accept it once in the browser:
```
# one-time: tool keypair and TLS cert (all live in instance/, gitignored)
openssl genrsa -out instance/private.key 4096
openssl rsa -in instance/private.key -pubout -out instance/public.key
openssl req -x509 -newkey rsa:2048 -keyout instance/tls-key.pem \
-out instance/tls-cert.pem -days 30 -nodes -subj "/CN=localhost"
# run
.venv/bin/python -m flask --app coldcall_lti run --port 5443 \
--cert instance/tls-cert.pem --key instance/tls-key.pem
```
Then open https://localhost:5443/healthz once and click through the
certificate warning (Advanced → Proceed).
`instance/lti_config.json` describes the saltire platform to the app.
The working shape (fill the session id — see the caveat below):
```json
{
"https://saltire.lti.app/platform": [
{
"default": true,
"client_id": "saltire.lti.app",
"auth_login_url": "https://saltire.lti.app/platform/auth",
"auth_token_url": "https://saltire.lti.app/platform/token/<SESSION>",
"key_set_url": "https://saltire.lti.app/platform/jwks/<SESSION>",
"private_key_file": "private.key",
"public_key_file": "public.key",
"deployment_ids": ["<DEPLOYMENT-ID-FROM-SALTIRE>"]
}
]
}
```
## saltire side
On https://saltire.lti.app → Test Platform → **Security Model**:
1. Set LTI version to **1.3.0**. The Platform Details panel then shows
the issuer, client id, deployment id, and the auth/token/jwks URLs —
copy these into `instance/lti_config.json`.
2. Set **Message URL** to `https://localhost:5443/lti/launch`.
3. Under **Tool Details**: Initiate login URL
`https://localhost:5443/lti/login`; Redirection URI(s)
`https://localhost:5443/lti/launch`; clear the tool's public keyset
URL (saltire's server cannot reach localhost) and instead paste the
contents of `instance/public.key` into the tool **Public key** box.
4. **Save**, then **Connect** launches the tool. The default saltire
user carries the Instructor role and lands on the instructor page,
with the fake "Telecommunications 101" roster synced via NRPS. To
test the student experience, change the role under **User** to
`http://purl.imsglobal.org/vocab/lis/v2/membership#Learner`, save,
and Connect again — you land on /me.
## Caveats
- **The token and jwks URLs embed a saltire session id** (the
`/token/s...`/`/jwks/s...` suffix). Anonymous saltire sessions get a
new id eventually, which breaks `lti_config.json` until you update
it. To keep a stable setup, use saltire's Save menu to store the
configuration under a saltire account and reconnect from there.
- saltire sometimes raises native browser dialogs (e.g. "save your
changes first" flows); nothing about that affects the tool under
test.
- The cookie-check interstitial (`cookies_allowed_js_check.html`) is
part of the app and required: pylti1p3's Flask adapter expects the
application to supply that template when `enable_check_cookies()` is
used.