> ## Documentation Index
> Fetch the complete documentation index at: https://docs.safeonlineexam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Canvas LTI 1.3 Endpoint and Deployment ID Settings

> Reference for Safe Online Exam LTI 1.3 issuer, JWKS, auth URL, deployment-ID policy, Canvas API base settings, and self-hosted Canvas considerations.

Safe Online Exam implements LTI 1.3 to integrate with Canvas LMS. The application ships with built-in defaults for the Canvas cloud endpoints, so most deployments only need to supply the client ID, deployment ID, and signing key. This page documents every LTI and Canvas endpoint variable, the deployment-ID validation policy, the course navigation visibility setting, and what to change for self-hosted Canvas installations.

<Tip>
  Before registering the tool in Canvas, verify that the JWKS endpoint is reachable and returns a valid key set by opening `${TOOL_URL}/lti/jwks` in a browser or with `curl`. Canvas fetches this endpoint during key verification, and an unreachable or malformed response will prevent successful LTI launches.
</Tip>

***

## Canvas and LTI Endpoint Variables

Canvas cloud defaults are built into the application. You only need to set these variables when connecting to a self-hosted Canvas installation that uses different endpoint URLs.

| Variable              | Default                                                | Notes                                                                                                                                       |
| --------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `LTI_ISSUER`          | `https://canvas.instructure.com`                       | Must equal the `iss` claim in Canvas launch tokens. Do not assume it equals `CANVAS_DOMAIN`.                                                |
| `LTI_KEY_SET_URL`     | `https://sso.canvaslms.com/api/lti/security/jwks`      | Canvas platform JWKS endpoint used to verify launch token signatures.                                                                       |
| `LTI_AUTH_URL`        | `https://sso.canvaslms.com/api/lti/authorize_redirect` | Canvas OIDC authorization endpoint for the LTI 1.3 login flow.                                                                              |
| `CANVAS_API_BASE_URL` | `${CANVAS_DOMAIN}/api/v1`                              | Derived from `CANVAS_DOMAIN` when not set. In hardened runtimes, must be the Canvas HTTPS origin followed by `/api/v1`.                     |
| `CANVAS_REDIRECT_URI` | `${TOOL_URL}/api/oauth2callback`                       | Derived from `TOOL_URL` when not set. If supplied explicitly, must equal `TOOL_URL` followed by `/api/oauth2callback` in hardened runtimes. |

All five values must be credential-free HTTPS URLs. The application rejects values containing embedded usernames, passwords, or fragment identifiers in hardened runtimes.

The registration document published at `${TOOL_URL}/lti/config` includes the login initiation URL, the launch redirect URL, and the tool's JWKS endpoint. Submit this URL to Canvas when configuring the LTI Developer Key.

`LTI_PRIVATE_KEY` is the tool's own RSA signing key — it is entirely separate from the Canvas platform JWKS at `LTI_KEY_SET_URL` and unrelated to the SEB configuration certificate. Generate it with `npm run generate:lti-key` and never reuse a key from another application.

***

## Deployment-ID Policy

### LTI\_DEPLOYMENT\_ID\_CHECKING\_ENABLED

`LTI_DEPLOYMENT_ID_CHECKING_ENABLED` controls whether the application validates incoming launch tokens against a preconfigured allowlist of deployment IDs.

| Value            | Behaviour                                                                                                                              |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `true` (default) | Launches are accepted only if the deployment ID in the token matches an entry in `LTI_DEPLOYMENT_ID`.                                  |
| `false`          | The preconfigured allowlist is not enforced. Any signed deployment ID from the configured Canvas issuer and LTI client ID is accepted. |

Set `LTI_DEPLOYMENT_ID_CHECKING_ENABLED=false` only when the Canvas issuer and LTI client ID are intentionally trusted to create course-level installations without prior allowlisting — for example, during a controlled self-service rollout across many courses.

<Note>
  Disabling the deployment-ID allowlist does **not** disable other security checks. Token signature verification, issuer validation, audience claim validation, nonce validation, target-link-URI binding, and browser/state binding all continue to run regardless of this setting. The only thing removed is the check against the list of known deployment IDs in `LTI_DEPLOYMENT_ID`.
</Note>

### LTI\_DEPLOYMENT\_ID

When `LTI_DEPLOYMENT_ID_CHECKING_ENABLED=true`, `LTI_DEPLOYMENT_ID` must be set to the deployment ID assigned by Canvas when the External App was installed. The value supports both comma-separated and newline-separated allowlists for deployments spanning multiple Canvas accounts or courses:

```text theme={null}
LTI_DEPLOYMENT_ID=123456789:school_abc,987654321:school_xyz
```

***

## Course Navigation Visibility

`LTI_COURSE_NAVIGATION_VISIBLE_TO_STUDENTS` controls whether the Safe Online Exam entry appears in Canvas course navigation for students.

| Value                                      | Canvas placement visibility | Effect                                                                                                                           |
| ------------------------------------------ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `true` (default, or any non-`false` value) | `members`                   | Students can see the Safe Online Exam navigation item in Canvas.                                                                 |
| `false` (case-insensitive)                 | `admins`                    | The navigation item is hidden from students. Students retain their protected-assessment LTI launch path for SEB-enabled quizzes. |

Only the exact case-insensitive string `false` selects `admins` visibility. Any other value — including an unset variable — preserves the `members` placement.

Setting `LTI_COURSE_NAVIGATION_VISIBLE_TO_STUDENTS=false` does not remove student access to SEB-required assessments. Students still complete the standard LTI launch sequence when accessing a quiz that requires Safe Exam Browser; only the sidebar navigation entry is hidden.

<Note>
  Changing `LTI_COURSE_NAVIGATION_VISIBLE_TO_STUDENTS` changes the generated placement metadata in the LTI configuration document. Existing Canvas registrations will not automatically pick up the change. After deploying with the new value, you must refresh the tool registration in Canvas by fetching the configuration from `${TOOL_URL}/lti/config`. Canvas stores the placement metadata at registration time and does not poll for updates automatically.
</Note>

***

## Self-Hosted Canvas Considerations

Self-hosted Canvas installations may use different issuer, JWKS, and authorization endpoint URLs than the Canvas cloud defaults. Override all three when connecting to a self-hosted instance:

<Tabs>
  <Tab title="Standard Canvas Cloud">
    No overrides required. The built-in defaults apply:

    ```text theme={null}
    # These are the defaults — only set them explicitly if you need to override
    LTI_ISSUER=https://canvas.instructure.com
    LTI_KEY_SET_URL=https://sso.canvaslms.com/api/lti/security/jwks
    LTI_AUTH_URL=https://sso.canvaslms.com/api/lti/authorize_redirect
    ```
  </Tab>

  <Tab title="Self-Hosted Canvas">
    Override all three endpoint variables to match your Canvas installation:

    ```text theme={null}
    LTI_ISSUER=https://canvas.yourinstitution.edu
    LTI_KEY_SET_URL=https://canvas.yourinstitution.edu/api/lti/security/jwks
    LTI_AUTH_URL=https://canvas.yourinstitution.edu/api/lti/authorize_redirect
    ```
  </Tab>
</Tabs>

`LTI_ISSUER` must equal the exact `iss` value in the Canvas launch request for your installation. Inspect a real launch token from your Canvas instance to confirm this value — do not assume it equals `CANVAS_DOMAIN`.

<Note>
  A self-hosted Canvas instance may retain the standard Canvas cloud issuer (`https://canvas.instructure.com`) even though it is running on a custom domain. This occurs when the instance was migrated from Canvas cloud or configured to use the shared SSO infrastructure. In that case, keep `LTI_ISSUER` at its default value and only override `LTI_KEY_SET_URL` and `LTI_AUTH_URL` if the endpoints differ.
</Note>

To confirm the correct values for your Canvas installation, check the Canvas Developer Keys settings page or contact your Canvas administrator. The issuer and endpoint URLs are also visible in the OIDC discovery document if your Canvas instance publishes one.

***

## Refreshing Canvas After Configuration Changes

Canvas caches the LTI tool configuration — including placement metadata and endpoint URLs — at registration time. After changing any of the following variables and deploying, you must re-fetch the configuration from Canvas to apply the update:

* `LTI_COURSE_NAVIGATION_VISIBLE_TO_STUDENTS` (changes placement visibility)
* `TOOL_URL` (changes all registered endpoint URLs)
* Any `LTI_*` endpoint variable

To refresh the Canvas registration, navigate to your Canvas instance's **Developer Keys** or **External Apps** settings, locate the Safe Online Exam registration, and update it by pointing Canvas at the configuration URL:

```text theme={null}
${TOOL_URL}/lti/config
```

Canvas will re-fetch the JSON configuration document and store the updated placement metadata, login URL, redirect URL, and JWKS reference. Existing course installations that reference this developer key will pick up the new configuration automatically.
