# 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.

[Canonical HTML page](https://safeonlineexam.com/docs/canvas/install-app)

With the LTI key enabled, install the external app so it appears in Canvas
navigation.

<Steps>
  <Step>
    ### Add the app by client ID [#add-the-app-by-client-id]

    At the root account (or the desired account scope), open the external-app
    configuration area and add the app **by client ID**. Paste the `LTI_CLIENT_ID`
    from the [LTI key](/docs/canvas/lti-key) step and approve the registration.
  </Step>

  <Step>
    ### Record the deployment ID [#record-the-deployment-id]

    Canvas assigns a **deployment ID** on installation. Record it — it becomes
    `LTI_DEPLOYMENT_ID`.
  </Step>

  <Step>
    ### Deploy a revision with the real IDs [#deploy-a-revision-with-the-real-ids]

    Set `LTI_DEPLOYMENT_ID` (and the real `LTI_CLIENT_ID`) and finalize the installer
    before testing. The Cloud Run release bundle creates numbered Secret Manager
    versions for the LTI values, stages a candidate revision, and cuts traffic only
    after readiness. The Compose bundle updates the protected environment and
    recreates the app through its migration gate.

    By default, the service **rejects** launches from a deployment ID that is not
    explicitly configured.
  </Step>
</Steps>

## Choose the deployment-ID policy [#choose-the-deployment-id-policy]

<Cards>
  <Card title="Strict (default)" description="LTI_DEPLOYMENT_ID_CHECKING_ENABLED=true. Only the deployment ID(s) you configure are accepted. Use this for controlled, admin-installed rollouts. Supports a comma/newline allowlist for multiple installs." />

  <Card title="Controlled self-service" description="LTI_DEPLOYMENT_ID_CHECKING_ENABLED=false. Accepts any non-empty deployment ID in a signed launch from the configured issuer and client ID — for letting instructors add this exact app to their own courses." />
</Cards>

<Callout type="warn" title="Only relax checking if the installers are trusted">
  Self-service mode still enforces token signatures, issuer/audience, nonce,
  target-link, and browser/state validation — it removes only the preconfigured
  allowlist. Use it only if **everyone** who can install this client ID in Canvas is
  trusted to grant access to the tool.
</Callout>

## Choose the account scope [#choose-the-account-scope]

| Scope                     | Use it for                                                                                           |
| ------------------------- | ---------------------------------------------------------------------------------------------------- |
| Root-account installation | A broad rollout **and** the school administrator dashboard. Recommended.                             |
| Course-level installation | An isolated instructor/student pilot only. Does **not** provide the root-account navigation surface. |

<Callout>
  Do not install the same registration both account-wide and course-local in the
  same course unless you intend duplicate navigation entries.
</Callout>

## Hiding the student navigation tab [#hiding-the-student-navigation-tab]

You may hide the **Safe Online Exam** course-navigation placement from students
without breaking protected Classic Quiz or New Quiz launches. Keep the external
app installed in the course or inherited from its account. On an assessment page
where the tab is not rendered, the detector uses the student's same-origin Canvas
session to find the installed LTI 1.3 tool that matches the configured client and
deployment IDs, then starts the signed assessment launch.

On a sharded Canvas instance, the External Tools list can return the same Developer
Key as a shard-local ID while `LTI_CLIENT_ID` remains globally qualified. The
detector recognizes that corresponding form; do not replace the configured client
ID with another local or unrelated Developer Key ID.

This remains subject to the deployment-ID policy above: strict mode requires a
matching configured deployment ID, while controlled self-service mode accepts a
signed launch for the configured client ID. Test the hidden-tab path before a real
exam; the acceptance sequence is in [Roll out & operate](/docs/operate).

If the tool does not launch, or the admin dashboard is missing, see
[Troubleshooting → Canvas launch](/docs/troubleshooting/canvas-launch).

Next: [Load the detector script](/docs/canvas/detector-script).