Canvas LMS Integration Guide

1. How it works

The integration of the proctoring system with the Canvas LMS is done using the Learning Tools Interoperability (LTI) and the Supervisor SDK (JavaScript proctoring library). First, you need to place the custom SDK code on one of the HTML pages in the LMS, and then configure the LTI in the course module to access proctoring through the LMS.

2. Setting up a quiz element

Go to your course and open your quiz in preview mode. Copy the quiz URL from your browser's address bar to use later as the “url” custom parameter from Section 4. To prevent the quiz from being opened without proctoring you should set up access restrictions to the quiz by code. To do this, you need to enable the "Access code required" option in the quiz element settings:

Setting the access code
Setting the access code

When running an assessment under proctoring, which is limited by an access code, the code will be automatically inserted into the input field and the participant will be able to start the assessment. In addition, you can restrict access to the quiz without proctoring after the access code is entered correctly the first time. To do this, just add the word “proctoring” to the quiz title. Note that this only works if you upload the proctoring script using the Theme Editor (see Section 3.1).

3. Upload the proctoring script

For proctoring to work, you need to place the SDK code on the Canvas LMS page with the same domain as the quiz. This is required for opening the quiz in IFRAME within the proctoring session without cross-origin issues.

3.1. Using theme editor

You can use the Theme Editor in Canvas LMS to inject the proctoring code into all pages in the LMS. This method is described in this guide. To do this, follow these steps:

  1. Create a “proctoring.js” file on your computer with the following content:

JavaScript

(function (host) {
 if (window.self === window.parent) {
   if (window.ENV && window.ENV.current_user_roles.includes('student')) {
     if (/^\/courses\/\d+\/quizzes\/\d+/.test(location.pathname)) {
       var title = document.getElementById('quiz_title');
       if (title && /proctoring/.test(title.innerText)) {
         var block = document.getElementById('not_right_side');
         if (block) block.innerHTML = '<h1>Access Denied</h1>';
       }
     }
   }
   var params = new URLSearchParams(location.search);
   if (params.get('token')) {
     var script = document.createElement('script');
     script.setAttribute('src', `https://${host}/sdk/supervisor.js`);
     script.onload = function () {
       var supervisor = new window.Supervisor({ url: `https://${host}` });
       supervisor.on(['fail', 'stop'], function () {
         supervisor.logout({ redirect: true });
       });
       supervisor.sync({ token: params.get('token') }).then(function () {
         return supervisor.start();
       });
     };
     document.head.appendChild(script);
   }
 }
 else {
   $(document).on('submit', function (e) {
     var form = e.target;
     if (/post/i.test(form.method)) {
       var url = new URL(form.action);
       var xhr = new XMLHttpRequest();
       xhr.open('POST', form.action);
       xhr.addEventListener('load', function () {
         location.href = url.searchParams.get('next_question_path') || url.href;
       });
       xhr.send(new FormData(form));
       e.preventDefault();
     }
   });
 }
})('demo.proctoring.app');

NOTE: you need to replace "demo.proctoring.app" with the domain of your proctoring server in the script code.

  1. Enable the ability to load custom JavaScript in "Admin" → "Settings" → "Features" → "Custom CSS/JavaScript overrides".

    Enabling custom JS loading
    Enabling custom JS loading

  2. Open the current theme in the theme editor "Admin" → "Themes" → "Open in Theme Editor" and upload the file "proctoring.js" section of the editor "Upload" → "JavaScript file".

    Uploading the JavaScript file
    Uploading the JavaScript file

  3. Save your changes by clicking the “Preview Your Changes”, then the “Save theme” and "Apply theme" buttons.

  4. Use this URL in the Launch URL from Section 4 in the “redirect” parameter:

    https://demo.proctoring.app/api/auth/canvas?redirect=https://your-canvas-server

NOTE: you need to replace "demo.proctoring.app" with the domain of your proctoring server and “your-canvas-server” with your Canvas server domain.

3.2. Using file uploading

If the previous method does not work, you can upload the proctoring script as an HTML file and use a link to the file in the LTI Tool URL with the redirect parameter. To do this, follow these steps:

  1. Create a “proctoring.html” file on your computer with the following content

JavaScript

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <title>Proctoring</title>
</head>
<body>
 <p>There is nothing here. This is a service page for proctoring.</p>
 <script src="//demo.proctoring.app/sdk/supervisor.js" data-supervisor="sync"></script>
 <script>
   if (window.supervisor) {
     supervisor.on('load', function (iframe) {
       var { contentDocument, contentWindow } = iframe;
       contentWindow.$(contentDocument).on('submit', function (e) {
         var form = e.target;
         if (/post/i.test(form.method)) {
           var action = form.action;
           var url = new URL(action);
           var xhr = new XMLHttpRequest();
           xhr.open('POST', action);
           xhr.addEventListener('load', function () {
             contentWindow.location.href = url.searchParams.get('next_question_path') || url.href;
           });
           xhr.send(new FormData(form));
           e.preventDefault();
         }
       });
     });
   }
 </script>
</body>
</html>

NOTE: you need to replace "demo.proctoring.app" with the domain of your proctoring server in the script code

  1. Go to the “Files” section of your course and upload the “proctoring.html” file. Then click on the uploaded file and copy the URL from your browser's address bar.
    Uploading the HTML file
    Uploading the HTML file

Example of the URL: https://your-canvas-server/courses/1/files?preview=2

  1. Replace the URL from the preview format to the standalone page format:
    • Source URL: /courses/<course_id>/files?preview=<file_id>
    • Target URL: /courses/<course_id>/files/<file_id>/preview
  2. Use this URL in the Launch URL from Section 4 in the “redirect” parameter:

    https://demo.proctoring.app/api/auth/canvas?redirect=https://your-canvas-server/courses/1/files/2/preview

NOTE: you need to replace "demo.proctoring.app" with the domain of your proctoring server and “your-canvas-server” with your Canvas server domain.

Sometimes it does not work because the domain for uploading files is different from the quiz domain (e.g. the Instructure.com cloud). In this case, you should try the next method.

4. Adding an application

First, you need to add a new application to your course settings (or entire Canvas instance settings). To do this, go to "Settings" → "Apps" → "Add App" and in the window that opens, fill in the fields according to the following sample:

  • Configuration type: Manual Entry
  • Name: Proctoring
  • Consumer key: demo

this key for your proctoring server is issued by the manager

  • Shared secret: secret

this key for your proctoring server is issued by the manager

  • Launch URL: https://demo.proctoring.app/api/auth/canvas?redirect=<sdk_page>

the demo.proctoring.app is used as an example only, please specify the address of your proctoring server instead; <sdk_page> is a page with the proctoring script code, or the Canvas home page if you used the Theme Editor.

  • Domain: demo.proctoring.app

the demo.proctoring.app is used as an example only, please specify the address of your proctoring server instead

  • Privacy: Public
  • Custom fields:
Key
Value
template
default
members
@

url=<quiz_url> (format "/courses/<course_id>/quizzes/<quiz_id>/take") code=<quiz_password>

Colored fields should be replaced with your values. You can specify additional parameters in the KEY=VALUE format in the custom fields, if necessary. These are the parameters that will be sent to the proctoring system when the test-taker starts the application. In the “url” parameter you should specify the URL to the quiz in Canvas LMS. In the “code” parameter you should specify the access code to the quiz.

Adding an application
Adding an application

5. Adding an external tool

Now you need to add a new course element to a specific module. To do this, go to "Modules" → "[+] Add Item". In the window that opens, select "External Tool" and highlight the added application in the previous step. The fields "URL" and "Page Name" are filled in automatically, and the checkbox "Load in a new tab" must be checked manually.

Setting external tool parameters
Setting external tool parameters

If you want to add an LTI app to an entire instance of Canvas and use it in any course, you can do this without specifying LTI custom fields such as "url" or "template". Instead, you can bypass the "url" or "template" parameter in the URL field when adding the application to the course module.

The URL looks like this:

https://demo.proctoring.app/api/auth/canvas?redirect=https://your-canvas-server&template=quiz1&url=/courses/<course_id>/quizzes/<quiz_id>/take

6. Use of proctoring

Now, when a test-taker navigates through the proctoring link, they will begin to take an associated quiz according to the proctoring workflow. Clicking on the proctoring link takes an administrator or teacher to the proctoring interface, where they can access all sessions and their reports created by that link.

The proctoring link
The proctoring link

7. Setting up the proctoring host

To connect the integration API with Canvas LMS, you need to load the following config with integration parameters under the proctoring system manager:

JSON

{
 "id": "<Host_ID>",
 "key": "<License_Key>",
 "params": {
   "webhooks": {
     "canvas": {
       "authorizer": "lti",
       "integrator": "lti",
       "consumerKey": "demo",
       "consumerSecret": "secret",
       "callbackURL": "query.redirect",
       "profile": {
         "username": "payload.user_id",
         "role": "payload.roles.find(v=>/Instructor/.test(v))?'proctor':'student'",
         "nickname": "payload.lis_person_name_full",
         "lang": "(payload.launch_presentation_locale||'').slice(0,2)",
         "group": "['G',payload.context_id,payload.resource_link_id].join('-')",
         "referrer": "payload.launch_presentation_return_url",
         "labels": "payload.lis_person_contact_email_primary"
       },
       "register": {
         "identifier": "[payload.user_id,payload.context_id,payload.resource_link_id].join('-').replace(/[^A-Za-z0-9_-]+/g,'_')",
         "template": "query.template||payload.custom_template",
         "subject": "payload.resource_link_title",
         "members": "payload.custom_members==='@'?user.group:payload.custom_members",
         "url": "query.url||payload.custom_url",
         "code": "payload.custom_code",
         "tags": "payload.lis_person_contact_email_primary"
       },
       "start": true,
       "stop": true,
       "pause": true,
       "submit": true
     }
   }
 }
}

NOTE: the fields consumerKey and consumerSecret need to be replaced with a randomly generated sequence of characters (Latin letters of different case and numbers, the recommended length is 24 characters); id is the ID of the host (if you do not specify it, a new host will be created); key is the license key of this host.