hypothesis / hypothesis/product-backlog
Canvas Studio videos not working correctly when embedded in Canvas Pages and shown in the LMS app
- Dominant language
- No language data
- Stars
- 122
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
**The issue**
Canvas Studio videos that are embedded directly in a Canvas Page don't play when a student opens that page through the Hypothesis LMS app. The video area loads, but instead of the player, it appears to try to load the institution's login screen inside the small video frame. YouTube videos embedded on the same pages play normally.
**Claude notes:**
Observed (from a HAR capture):
- The Studio video's iframe makes a request to Canvas's own `GET /courses/:id/external_tools/retrieve?...&custom_arc_media_id=...` endpoint (Canvas's LTI content-retrieval route for Studio/Arc).
- That request gets routed through Via's HTML proxy (`lms-viahtml.hypothes.is/proxy/if_//courses/:id/external_tools/retrieve...`) rather than going directly from the student's browser to Canvas.
- The proxied request comes back as a 302 redirect to `/login`.
- The page's Via URL already includes `via.proxy_frames=0` — an existing setting (`lms/views/api/canvas/pages.py`, referencing `hypothesis/support#98`) whose stated purpose is to let embedded widgets that require authentication bypass Via's proxying.
- YouTube embeds on the same pages get proxied through the same mechanism (`.../proxy/if_/https://www.youtube-nocookie.com/embed/...`) but return 200 successfully, since they don't require a session.
- `viahtml`'s client-side rewriting script (`wombat.js`) loads on these pages in both cases.
Interpreted (not directly confirmed):
- Working theory: `via.proxy_frames=0` only prevents server-side HTML rewriting from inserting a proxied URL into the iframe's `src` at the time the page is served (`viahtml/hooks/hooks.py`, `Hooks.modify_tag_attrs`). It has no counterpart on the client side, where `wombat.js` independently intercepts and rewrites absolute URLs at the point of navigation. If that's right, it would explain why the setting doesn't actually stop this iframe from being proxied, regardless of DesignPlus.
- We have not stepped through `wombat.js`'s source to directly confirm it's the specific mechanism doing the re-proxying — only that its presence and behavior are consistent with that explanation.
**What's needed**
Canvas Studio videos embedded in a Canvas Page need to actually launch and play for students inside the Hypothesis assignment, the same way they already do for the instructor viewing the page directly in Canvas — regardless of whether the page was authored with a tool like DesignPlus or with Canvas's own editor.
Note: It's not expected that students will be able to annotate over the transcript of an embedded Canvas Studio video; that's only expected in Studio-specific assignments. All that's needed is for the Studio video to be visible to students loading the Page through a Hypothesis assignment.
**Possible solution**
Find a way for the video's request back to Canvas to go out as if the student's own browser were making it directly — carrying their normal Canvas login — rather than having Hypothesis's proxy make that request on the student's behalf without their session attached.
**Claude notes:**
- If the `wombat.js` theory holds, a fix likely needs to happen at the same layer that already special-cases certain embeds — either extending `viahtml/hooks/hooks.py`'s existing `MEDIA_EMBED_PREFIXES` allow-list (added for Kaltura/Vimeo/YouTube in `hypothesis/support#28`) or fixing the `proxy_frames` mechanism itself (`hypothesis/support#98`) so it also suppresses client-side re-proxying, not just the server-side HTML substitution. There's already a `data-viahtml-no-proxy` attribute honored server-side — worth checking whether `wombat.js` respects it too, or could be taught to.
- A simple prefix-based allow-list like `MEDIA_EMBED_PREFIXES` won't generalize as cleanly here: the offending URL is Canvas's own generic `/courses/:id/external_tools/retrieve` endpoint, which varies per Canvas instance rather than being a single fixed hostname like `player.vimeo.com`. Any fix probably needs to key off the path pattern (`/external_tools/retrieve`) or the `instructuremedia.com` LTI launch URL passed in its query string, not a fixed domain.
- `lms/services/canvas_studio.py` already solves an analogous problem — Canvas Studio auth without relying on the student's own browser session — using a server-side admin API token, for the case where a Studio video is chosen as the assignment's document via the file picker. That pattern may be worth a look, though the two cases differ (there it's the assignment's whole document; here it's one embed inside a page's body).
- Not yet tested: whether stopping the proxying is sufficient by itself, or whether something else in the nested-iframe context (e.g., third-party cookie restrictions on the Canvas session cookie itself, independent of Via) would still interfere. Worth confirming end-to-end — bypass the proxying however it ends up implemented, and check the video actually plays — before assuming that's the whole fix.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reading lms/views/api/canvas/pages.py and viahtml/hooks/hooks.py, then inspect wombat.js to confirm whether client-side rewriting re-proxies the Canvas Studio request. Review lms/services/canvas_studio.py for the existing authentication approach and reproduce the issue end to end. Done means an embedded Studio video plays for students in a Hypothesis assignment while YouTube embeds continue to work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, python
- Domain
- authentication, backend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100