0045. H5P learner state through the BFF; no API token in the browser
Generated from docs/decisions/0045-h5p-state-through-bff.md
- Status: Proposed
- Date: 2026-10-09
- Plan:
docs/plans/leftovers-0-2.md(L1-06)
Context and problem statement
Section titled “Context and problem statement”The Astro front keeps the learner’s API token in an httpOnly session cookie (ADR 0008). The H5P
frame receives token: null, so the H5P service cannot load or save the learner’s state.
Considered options
Section titled “Considered options”- The BFF’s
/h5p/*proxy addsAuthorizationon the server side, for an allow-list of H5P paths. - Mint a short-lived scoped token and post it into the H5P frame.
Decision
Section titled “Decision”Option 1. The proxy injects the session’s bearer token only for the H5P content-user-data, finished-data and play/embed routes of the H5P host, never for other hosts. The frame protocol is unchanged.
Implementation notes
Section titled “Implementation notes”- Allow-list (
front/web/src/lib/h5p-proxy.ts):GET embed/play/<id>,GET contents/<id>/play,GET|POST contentUserData/<id>/<type>/<sub>andPOST finishedData. Every other route, and every other method, is forwarded without the session. The session token is added only on the server and only to the tenant API host; a_tokensent by the caller is dropped. - The play model would otherwise put the learner’s token into its AJAX URLs (
?_token=, because H5P core cannot send a header). The proxy marks its requests withX-Ulams-Session-Proxy: 1; the H5P service then leaves the token off the user, so the URLs carry none and the frame’s calls go back through the same proxy.api/h5p/src/auth/middleware.tsis the only service change. - The progress endpoint
POST /api/courses/progress/{topic}/h5paccepts the statement object the SDK sends asevent: it is stored as the JSONdata, its verb IRI as the event.
Consequences
Section titled “Consequences”- Good: no bearer token is ever exposed to third-party H5P content scripts.
- Good: token refresh stays in one place.
- Bad: H5P traffic for logged-in learners passes through the Astro server, adding a small latency.
- Default pending #51.