Load the detector script
Add the detector via a Canvas theme JavaScript loader so it runs on quiz pages, and handle the self-hosted Canvas local-file (HTTP 422) case.
The detector runs on Canvas quiz-taking pages. It launches the protected SEB flow, fills the access code only after Config Key proof, shows approved web tools, and detects Canvas-confirmed completion. It reaches those pages by being loaded through your Canvas account theme JavaScript.
The stable script URL is:
${TOOL_URL}/js/canvas-seb-detector.jsCreate the loader
Upload a small loader (not the detector itself) as the theme's desktop
JavaScript. Replace ${TOOL_URL} before uploading.
(function () {
"use strict";
const detectorUrl = "${TOOL_URL}/js/canvas-seb-detector.js";
const assessmentPath = /^\/courses\/\d+\/(?:quizzes\/\d+\/take|assignments\/\d+)(?:\/|$)/;
if (!assessmentPath.test(window.location.pathname)) {
return;
}
if (document.querySelector('script[data-canvas-seb-detector="true"]')) {
return;
}
const script = document.createElement("script");
script.src = detectorUrl;
script.async = true;
script.dataset.canvasSebDetector = "true";
document.head.appendChild(script);
})();The pattern matches Classic Quiz /take pages and New Quiz assignment routes
(including their Canvas-generated descendants). script.src must be a plain
JavaScript URL string — not a Markdown link.
Upload as theme JavaScript
Upload the loader as the account theme's desktop JavaScript and apply the theme at the intended account scope.
Confirm it applies at the right scope
Theme upload capability and inherited-theme behavior vary by Canvas configuration. If the upload control is unavailable, resolve that account setting before treating the detector as installed.
Retest after Canvas changes
Retest the loader after significant Canvas theme, CSP, or quiz-rendering changes.
Self-hosted Canvas: the local-file (HTTP 422) case
Some self-hosted Canvas deployments store an uploaded theme JavaScript file as a
local /accounts/:accountId/files/:fileId/download attachment. Rails can reject
that response with ActionController::InvalidCrossOriginRequest (HTTP 422), so
the loader never reaches the service. This is a Canvas attachment-serving
limitation — not an LTI, detector, or deployment-ID failure.
Do not disable CSRF protection
When the browser console shows that 422, do not disable Canvas CSRF
protection globally. Instead, point the account theme's js_overrides value at the
externally hosted loader:
${TOOL_URL}/js/canvas-seb-theme-loader.jsThe hosted loader keeps the same quiz-route scope and loads the full detector only
on Classic Quiz /take pages and New Quiz assignment routes. Canvas's Theme Editor
has no direct URL field, so set this through your provisioning/administration path
and preserve it on future theme saves. For a one-off root-account recovery, run
this inside the Canvas web container (replace the account ID and URL):
bundle exec rails runner '
account = Account.find(1)
current = account.brand_config || BrandConfig.default
attrs = current.attributes.slice(*BrandConfig::ATTRS_TO_INCLUDE_IN_MD5.map(&:to_s))
attrs["js_overrides"] = "https://seb.example.edu/js/canvas-seb-theme-loader.js"
replacement = BrandConfig.for(attrs.symbolize_keys)
replacement.save_unless_dup!
replacement.sync_to_s3_and_save_to_account!(nil, account)
'For a broader deployment, configure S3-compatible attachment storage and re-upload the theme file — Canvas then serves uploaded theme assets from object storage instead of the local files controller. That is the durable fix for arbitrary uploaded theme JavaScript; the hosted loader is the smallest safe fix for this integration.
The service also exposes /api/seb/canvas-detector.js as a compatibility alias for
an existing installation that uses that path. New loaders should use
/js/canvas-seb-detector.js.
Verify the detector loaded
In a normal browser, open a Classic Quiz /take page and a New Quiz assignment
route and confirm the detector script loads without console errors, and that
${TOOL_URL}/js/canvas-seb-detector.js returns JavaScript. If it never loads, see
Troubleshooting → Detector.
Next: verify everything end to end in Roll out & operate.
Install the external app
Install the registered app by client ID at the right account scope, record the deployment ID, and choose between strict and self-service deployment-ID policy.
Self-hosted Canvas
Endpoint overrides, issuer rules, platform signing-key requirements, and the launch-error recovery table for Canvas instances you run yourself.