Canvas LTI Integration: A Practical Guide for Admins and Developers

A two-track walkthrough of Canvas LTI 1.3 and LTI Advantage: the exact Developer Key fields an admin fills in, the OIDC/JWT endpoints a developer builds, how AGS returns grades to the gradebook, and the launch errors that break real deployments.

July 26, 202619 min read
AE
By Assignify Editorial Staff
Canvas LTI Integration: A Practical Guide for Admins and Developers

Canvas fully supports LTI 1.3 and LTI Advantage, the current standard for secure, grade-aware tool launches, and getting a working integration requires two parallel tracks: an administrator creating and enabling a Developer Key in Canvas, and a developer building the OIDC/JWT endpoints on the tool side. Before you touch a single Canvas menu, run through this starting checklist.

Admin first steps:

  • Confirm which Canvas environment you are working in: production, beta (beta.instructure.com), or test (test.instructure.com). Always start in beta or test.
  • Collect from the tool provider: OIDC initiation URL, redirect URI(s), JWKS URL, and either a configuration JSON/URL or the manual parameters.
  • Decide which LTI Advantage services you need: Assignment and Grade Services (AGS), Names and Roles Provisioning Service (NRPS), Deep Linking, and Platform Notification Service (PNS).

Developer first steps:

  1. Expose an OIDC initiation endpoint that accepts Canvas's login request and returns a browser redirect (not a server-to-server call).
  2. Host a JWKS endpoint so Canvas can fetch your public keys for JWT verification.
  3. Register one or more redirect URIs that exactly match what you will give the admin for the Developer Key.
  4. Implement handlers for whichever Advantage services the integration requires (AGS score POST, NRPS roster fetch, Deep Linking response).

The role split is deliberate. Admins control what Canvas trusts; developers control what the tool does with that trust. Both sides must be in sync before a single launch succeeds.

What LTI is and why LTI 1.3 and Advantage matter for Canvas

Learning Tools Interoperability (LTI) is the 1EdTech standard that lets Canvas securely pass user identity, course context, and grade data to an external tool, and receive results back, without requiring students or instructors to log in twice. Think of it as a structured handshake: Canvas vouches for the user, the tool receives a signed token, and both sides agree on what data can flow between them.

LTI 1.1 used OAuth 1.0 signatures and XML-based messages. It still works in many legacy deployments, but it carries real limitations: no standardized grade-return API, no roster service, and a weaker security model that relies on shared secrets rather than asymmetric keys. LTI 1.3 replaces that with an OIDC-based launch flow and JWT payloads, which means Canvas signs every launch message with a private key and the tool verifies it against Canvas's published JWKS. That shift matters practically: you get cryptographic proof of who initiated the launch, not just a shared secret that could be replicated.

LTI Advantage layers three core services on top of LTI 1.3: AGS for grade return, NRPS for roster access, and Deep Linking for content selection. PNS adds asynchronous server-to-server notifications. Together, they cover the full lifecycle of a tool embedded in a course, from content selection through grading through roster sync.

Canvas-specific behavior: The OIDC login initiation step must be a browser redirect, not a server-to-server HTTP call. Canvas validates the end-user's session as part of the flow. Tools that attempt a server-side OIDC request will see launch failures that can be difficult to diagnose because the error surfaces in the browser, not in server logs.

Pro Tip: If you are migrating a tool from LTI 1.1 to LTI 1.3, do not assume the same placement configuration carries over. LTI 1.3 Developer Keys use a separate configuration path in Canvas, and you will need to re-register the tool and update any existing course-level placements.

How to configure a Developer Key and deploy your LTI tool in Canvas

This is the admin's core task. The Developer Key configuration in Canvas is where the trust relationship between Canvas and the tool is established. You need account-level admin permissions to complete these steps.

Creating the Developer Key

  1. Log into Canvas as an account admin and navigate to Admin > [Account Name] > Developer Keys.
  2. Click + Developer Key and select LTI Key from the dropdown.
  3. Choose your configuration method: Manual Entry (fill in each field individually) or Enter URL / Paste JSON (auto-imports values from the tool provider's registration endpoint). Importing via JSON or URL is strongly preferred, it reduces transcription errors and pulls in placement definitions automatically.
  4. Fill in or confirm the following fields:
    • OIDC Initiation URL: the tool's endpoint that starts the login flow.
    • Redirect URIs: one or more exact URIs where Canvas will POST the id_token. Canvas enforces exact matching: a trailing slash difference will break the launch.
    • JWK Method: select Public JWK URL and enter the tool's JWKS endpoint, or paste a static JWK if the tool does not host a rotating key set.
    • Domain and Tool ID (optional but useful for placement filtering).
  5. Under LTI Advantage Services, enable only the services the tool actually needs. Each toggle grants a specific permission scope:
    • Can create and view assignment data in the gradebook (AGS LineItems)
    • Can view assignment data in the gradebook (AGS Results, read-only)
    • Can create and update submission results (AGS Scores)
    • Can retrieve user data associated with the context (NRPS)
    • Can update public JWK (key rotation)
  6. Save the key. Canvas generates a Client ID, share this with the tool developer. It is the identifier the tool uses in its OIDC auth request.
  7. Toggle the key from Off to On in the Developer Keys list.

How to build an LTI 1.3 Advantage tool that works with Canvas

The OIDC-based launch flow has five distinct steps, and each one has a failure mode worth knowing before you write a line of code.

Minimal pseudocode: validating the id_token

# Step 1: Receive id_token POST at redirect URI
id_token = request.POST["id_token"]
state    = request.POST["state"]

# Step 2: Verify state matches stored value (CSRF protection)
assert session_store.get("lti_state") == state

# Step 3: Fetch Canvas JWKS and validate JWT
jwks = fetch_json("https://<canvas_domain>/api/lti/security/jwks")
claims = jwt.decode(
    id_token,
    jwks,
    algorithms=["RS256"],
    audience=CLIENT_ID,
    issuer="https://canvas.instructure.com"
)

# Step 4: Validate deployment_id
assert claims["https://purl.imsglobal.org/spec/lti/claim/deployment_id"] \
    in REGISTERED_DEPLOYMENT_IDS

Deep Linking response (Content-Item)

When Canvas launches your tool in Deep Linking mode, the message_type claim is LtiDeepLinkingRequest. Your tool presents a content picker, and when the instructor selects content, you POST a signed JWT back to the deep_link_return_url from the claims.

# Minimal Deep Linking response JWT payload
{
  "iss": CLIENT_ID,
  "aud": "https://canvas.instructure.com",
  "iat": now(),
  "exp": now() + 600,
  "nonce": generate_nonce(),
  "https://purl.imsglobal.org/spec/lti-dl/claim/data": dl_data,
  "https://purl.imsglobal.org/spec/lti-dl/claim/content_items": [
    {
      "type": "ltiResourceLink",
      "title": "Assignment Title",
      "url": "https://tool.example.com/launch",
      "lineItem": {
        "scoreMaximum": 100,
        "label": "Assignment Title",
        "resourceId": "assignment_001"
      }
    }
  ]
}

Including a lineItem in the Deep Linking response tells Canvas to create a gradebook column automatically, with no separate AGS LineItem creation call needed.

Key developer constraint: Canvas requires that your OIDC initiation handler issues a browser redirect. Any attempt to complete the OIDC handshake server-to-server will fail because Canvas validates the user's active browser session as part of the flow. This is the most common cause of "silent" launch failures where the tool receives no error but the launch never completes.

Pro Tip: Safari and some privacy-focused browsers block third-party cookies, which breaks the state parameter storage in a standard cookie. Implement the Platform Storage postMessage fallback: use lti.put_data to store state before the OIDC redirect and lti.get_data to retrieve it after the id_token POST. Without this, Safari users will see launch failures that work fine in Chrome.

The community reference implementation at doldsimo/lti-1.3-canvas-lms provides working launch handling and JWT validation code you can adapt as a starting point.

EndpointYour responsibilityCanvas's role
oidc_initiation_urlAccept login params, generate state/nonce, redirect to Canvas authSends login hint, client_id, lti_message_hint
OIDC auth endpointConstruct auth request URLValidates request, returns id_token via POST
Redirect URIValidate state, verify JWT, render contentPOSTs id_token and state
JWKS URLServe your public keys (for signing DL responses)Fetches to verify tool-signed JWTs
AGS / NRPS endpointsCall Canvas service URLs from JWT claimsEnforces scope, returns data or accepts scores

How grade return (AGS) and other LTI Advantage services map to Canvas

AGS is what makes an LTI tool a graded activity rather than just an embedded page. When you enable AGS on the Developer Key and include a lineItem in your Deep Linking response, Canvas creates a gradebook column. Your tool then POSTs scores to that column using the AGS Score API.

Service overview

ServiceWhat it does in CanvasRequired scope
AGS LineItemsCreates/reads gradebook columnshttps://purl.imsglobal.org/spec/lti-ags/scope/lineitem
AGS ScoresSubmits student scores to a columnhttps://purl.imsglobal.org/spec/lti-ags/scope/score
AGS ResultsReads existing scores (read-only)https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly
NRPSRetrieves course roster with roleshttps://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly
Deep LinkingLets instructor select content, creates line itemsEnabled via Developer Key toggle
PNSReceives async notifications (roster changes, etc.)Registered handler URL

Posting a score via AGS

The lineItem URL comes from the https://purl.imsglobal.org/spec/lti-ags/claim/endpoint claim in the launch JWT. Use it directly, do not construct it manually.

POST {lineItem_url}/scores
Authorization: Bearer {access_token}
Content-Type: application/vnd.ims.lis.v1.score+json

{
  "userId": "student_canvas_id",
  "scoreGiven": 87,
  "scoreMaximum": 100,
  "comment": "Step 3 correct; step 4 missing unit conversion.",
  "activityProgress": "Completed",
  "gradingProgress": "FullyGraded",
  "timestamp": "2026-03-15T14:30:00Z"
}

The access_token comes from Canvas's OAuth 2.0 client credentials endpoint using your client_id and private key. Canvas processes score submissions asynchronously: a 200 OK response confirms receipt, but the score may take a few seconds to appear in the gradebook.

Practical note on Deep Linking and AGS together: When an instructor selects content via Deep Linking and your response includes a lineItem object, Canvas creates the gradebook column at that moment. Subsequent AGS score POSTs to that line item's URL will populate the column without any additional setup. This is the cleanest path to grade-return: one Deep Linking response handles both content placement and gradebook column creation.

Pro Tip: Request the narrowest AGS scope that covers your use case. If your tool only submits scores and never reads them back, request only scope/score, not scope/lineitem and scope/result.readonly. Canvas displays the enabled scopes to admins during Developer Key review, and over-permissioned keys raise legitimate compliance concerns.

NRPS is useful when your tool needs to pre-populate a roster before students launch. Call the context_memberships_url from the NRPS claim with a Bearer token scoped to contextmembership.readonly. Canvas returns a paginated list of members with their roles, Instructor, Learner, TeachingAssistant, mapped to the LTI role vocabulary.

Six-step Assignify Canvas LTI flow: instructor deep-linking, selecting the assignment and rubric, student submission, Assignify auto-grading, the AGS score POST, and the grade appearing in the Canvas gradebook

Testing checklist and common launch/grade errors

Pre-launch checklist

  1. Developer Key is set to On in Canvas Admin > Developer Keys.
  2. Tool is added as an external app at account or course level using the correct Client ID.
  3. JWKS endpoint returns a valid JSON key set and is publicly reachable (test with curl).
  4. Redirect URI in the Developer Key exactly matches the URI the tool sends in its OIDC auth request, character for character, including protocol and trailing slashes.
  5. All required Advantage service scopes are enabled on the Developer Key.
  6. Test launch performed in Canvas beta or test environment before production.

Common errors and fixes

ErrorLikely causeFix
redirect_uri_mismatchURI in Developer Key differs from tool's OIDC requestCompare both values character by character; update the Developer Key
invalid_id_token / signature failureJWKS URL unreachable or wrong keyConfirm JWKS URL is public; check key ID (kid) matches
Missing deployment_id claimTool not added as external app after key creationAdd tool via Settings > Apps > By Client ID
Launch fails in Safari onlyThird-party cookie blockedImplement Platform Storage lti.put_data / lti.get_data postMessage fallback
AGS score POST returns 401Missing or wrong scope on Developer KeyEnable scope/score on the Developer Key; re-fetch access token
Score submitted but not visibleCanvas async processing delayWait 5 seconds; check gradingProgress: FullyGraded is set
Deep Linking response rejectedJWT signed with wrong key or expiredVerify exp claim; confirm tool signs with its own private key

Pro Tip: When diagnosing launch failures, open your browser's network tab and capture the full OIDC redirect chain. The id_token POST to your redirect URI is visible there, and you can decode the JWT payload at jwt.io to inspect every claim before your server-side validation runs. This saves significant debugging time compared to reading server logs alone.

  • For role propagation issues, launch as a student in a test enrollment and inspect the https://purl.imsglobal.org/spec/lti/claim/roles claim. Canvas maps its internal roles to LTI role URIs: http://purl.imsglobal.org/vocab/lis/v2/membership#Learner for students, #Instructor for teachers.
  • For grade-sync failures, confirm the lineItem URL in your score POST matches the one returned in the launch JWT, not a manually constructed URL.
  • For NRPS failures, verify the context_memberships_url claim is present in the launch JWT (it only appears when NRPS is enabled on the Developer Key).

Security and student-data privacy considerations for Canvas LTI integrations

Security in an LTI integration is not optional configuration. It is the foundation that makes the trust model work. Every endpoint in the flow must use HTTPS. Any tool that accepts an id_token over plain HTTP is vulnerable to token interception, and Canvas will not initiate launches to non-HTTPS endpoints in production.

Minimum security checklist:

  • All tool endpoints (OIDC initiation, redirect URI, JWKS, AGS/NRPS handlers) served over HTTPS with a valid certificate.
  • JWKS hosted at a stable, publicly reachable URL; implement key rotation on a defined schedule (annually at minimum) and support multiple active keys during the rotation window so in-flight launches do not fail.
  • Client secrets and private keys stored in environment variables or a secrets manager, never in source code or version control.
  • Least-privilege scopes: enable only the Advantage services the tool genuinely uses. Each additional scope is an additional attack surface.
  • nonce and state parameters validated on every launch to prevent replay attacks.
  • exp and iat claims validated; reject tokens older than a few minutes.

Privacy and FERPA guidance:

FERPA applies to any tool that receives student educational records, which includes names, user IDs, enrollment data, and grades. Before enabling a tool that receives NRPS roster data or AGS scores, administrators should confirm that a data processing agreement (DPA) is in place with the vendor. The DPA should specify data retention limits, access controls, and breach notification procedures. Our K–12 student data privacy compliance guide covers the clauses these agreements need in more depth.

Minimize PII in custom LTI claims. Canvas allows administrators to add custom parameters to a Developer Key, but each custom parameter that includes student data expands the tool's data footprint. If the tool only needs a pseudonymous identifier to correlate launches with scores, use Canvas's $Canvas.user.id substitution variable rather than passing name or email.

Pro Tip: Grant AGS only when grade sync is a core requirement of the tool's function. A tool that embeds reference content does not need AGS. A tool that embeds a graded quiz does. Reviewing scope assignments annually, especially after vendor updates, is a practical way to keep the integration's data permissions aligned with its actual use.

Practical examples: config URL flow and an Assignify grading tool walkthrough

What a provider's configuration URL/JSON contains

When a tool provider gives you a registration URL or JSON file, it typically encodes all the fields Canvas needs for the Developer Key in a single payload:

  • oidc_initiation_url
  • target_link_uri (default launch URL)
  • redirect_uris (array)
  • jwks_uri
  • scopes (requested Advantage services)
  • extensions with Canvas-specific placement definitions (course navigation, assignment selection, etc.)

Pasting this JSON into the Developer Key creation screen or entering the URL under "Enter URL" auto-populates every field. The admin still reviews and enables the key, auto-import does not bypass the approval step, but it eliminates the transcription errors that plague manual entry.

Assignify in a Canvas LTI workflow

Assignify uses Deep Linking and AGS together to create a grading workflow that lives entirely inside Canvas. When an instructor adds an Assignify assignment to a Canvas course, the Deep Linking launch presents the assignment configuration interface. The instructor selects the assignment and grading rubric; Assignify's response JWT includes a lineItem that Canvas uses to create the gradebook column automatically.

When a student submits handwritten work, Assignify's multi-agent grading engine evaluates the submission, generates step-by-step feedback, and POSTs the score and comment to the AGS Score API. The instructor sees the grade in the Canvas gradebook alongside Assignify's detailed annotations, with no separate login and no grade-transfer step. For institutions managing large STEM cohorts, this means automated handwritten grading that preserves full instructor visibility in Canvas.

Staging vs. production redirect changes: When you move Assignify (or any tool) from a sandbox to production, update the Developer Key's redirect URIs before the first production launch. The safest approach is to add the production URI to the existing key while keeping the staging URI active, test the production launch, then remove the staging URI. Removing the staging URI first will break any active sandbox testing.

Pro Tip: A minimal smoke-test workflow for any LTI grading tool: (1) instructor launches Deep Linking, selects content, confirms gradebook column appears; (2) student launches the assignment, completes it; (3) check Canvas gradebook for score within 30 seconds. If the score does not appear, inspect the AGS score POST response in your tool's logs before touching Canvas configuration.

One-page quick checklist for admins and developers

Administrator checklist

  • Developer Key created and set to On in Admin > Developer Keys.
  • Correct Advantage services enabled (AGS, NRPS, Deep Linking, PNS), only those the tool requires.
  • Tool added as external app at account or course level via Client ID.
  • Placements configured (course navigation, assignment selection, or module item as needed).
  • Test course created with at least one instructor and one student enrollment.
  • Launch tested in Canvas beta/test environment; redirect URI confirmed exact match.
  • Data processing agreement reviewed with vendor before enabling NRPS or AGS.

Remediation hints: If the tool does not appear in course navigation, check that the course navigation placement is enabled on the Developer Key. If the launch fails immediately, the most likely cause is a redirect URI mismatch. Compare the Developer Key value with what the tool sends in its OIDC request.

Developer checklist

  1. OIDC initiation endpoint returns a browser redirect (HTTP 302) to Canvas's auth endpoint, confirmed with a real browser request, not a server-side HTTP client.
  2. JWT validation passes: signature verified against Canvas JWKS, iss matches https://canvas.instructure.com, aud matches your client_id, exp is in the future.
  3. JWKS endpoint publicly reachable and returns a valid JSON key set, confirmed with curl from an external network.
  4. state and nonce parameters generated, stored, and validated on every launch.
  5. deployment_id claim validated against registered values.
  6. AGS score POST returns 200 OK in test environment; score visible in Canvas gradebook within 30 seconds.
  7. Deep Linking response JWT signed correctly; Canvas creates gradebook column on instructor content selection.
  8. Platform Storage postMessage fallback implemented and tested in Safari.

Remediation hints: A 401 on AGS calls almost always means the access token was fetched with the wrong scope or the Developer Key scope was not enabled. A Deep Linking response that Canvas rejects is usually a JWT signing error. Verify you are signing with your tool's private key, not Canvas's.

Key Takeaways

A working Canvas LTI integration requires LTI 1.3 / Advantage, a correctly configured Developer Key with exact redirect URI matching, verified OIDC/JWT flows, and only the Advantage service scopes the tool genuinely needs.

PointDetails
Use LTI 1.3 / AdvantageLTI 1.3 with OIDC/JWT is the required standard for new Canvas integrations; LTI 1.1 lacks AGS and NRPS.
Exact redirect URI matchingCanvas enforces character-for-character redirect URI matching; a single trailing slash difference breaks every launch.
Test in beta/test firstAlways validate Developer Key config, JWKS, and AGS calls in Canvas beta before touching production.
Minimize Advantage scopesEnable only AGS, NRPS, or PNS when the tool's function requires them; over-permissioned keys create FERPA exposure.
Assignify for STEM gradingAssignify uses Deep Linking and AGS to return step-by-step feedback and scores directly into the Canvas gradebook.

Why the LTI rollout conversation is missing a key step

Most LTI deployment guides stop at "get the launch working," and that is exactly where the real operational risk begins. A launch that works in a demo environment and a launch that works reliably across 500 student submissions in week three of a semester are different problems.

The piece that gets skipped most often is the grade-sync monitoring window. AGS score POSTs are asynchronous, and Canvas processes them in a queue. Under normal load, scores appear within seconds. Under peak load, end-of-term submission rushes for example, that queue can back up. Instructors who check grades immediately after a submission window closes may see incomplete data and assume the integration is broken. The fix is not technical; it is communication. Set expectations with faculty before the first graded activity goes live.

The second underestimated issue is the Safari / third-party cookie problem. Most institutions test integrations in Chrome on a managed device. Safari is common among students on personal MacBooks and iPads. A tool that has not implemented the Platform Storage postMessage fallback will silently fail for a meaningful portion of your student population, and those students will report it as a Canvas bug, not a tool bug. Implement the fallback before any student-facing rollout, not after the first support ticket.

On the policy side: data processing agreements are not a legal formality. They define what happens to student grade data if the vendor is acquired, changes their data retention policy, or experiences a breach. Reviewing DPA terms before enabling AGS is the kind of step that takes 30 minutes and can prevent a FERPA incident that takes months to resolve.

Stage your rollouts by department. A single pilot course with a willing faculty member reveals configuration issues, role-propagation edge cases, and grade-visibility gaps before they affect an entire institution. The first grading cycle is your real integration test.

Diagram of the operational steps most LTI rollout plans skip, including grade-sync monitoring and Safari cookie fallback

Assignify brings LTI-ready AI grading directly into your Canvas gradebook

STEM educators managing large cohorts know the specific weight of a grading backlog: handwritten problem sets, multi-step proofs, lab reports that require line-by-line review. Assignify was built for exactly that workload. It connects to Canvas via LTI Advantage, uses Deep Linking so instructors can assign work directly from the Canvas course, and returns step-by-step AI-generated feedback and scores through AGS, so every grade lands in the Canvas gradebook without a manual transfer step.

Assignify AI grading platform interface

What Assignify automates goes beyond a single score: multi-agent grading checks each submission for consistency and fairness, analytics dashboards surface class-wide performance patterns, and the feedback annotations give students the kind of detailed, step-wise guidance that would take an instructor hours to write by hand. For institutions piloting the tool, testing in a sandbox course first lets your team validate the Deep Linking flow, confirm AGS score delivery, and review the feedback quality before any student-facing rollout.

Apply for beta access to set up a test course and run the full LTI Advantage workflow, launch, grade return, and analytics, before committing to institution-wide deployment.

Authoritative sources for Canvas and LTI developer documentation

The sources below cover the full implementation path, from initial concept to production debugging.

Statistic callout: 1EdTech's LTI Advantage specification defines three mandatory extension services, AGS, NRPS, and Deep Linking, as the baseline for any tool claiming full Advantage compliance. Implementing all three, rather than just the launch flow, is what separates a grade-aware integration from a simple embedded link.

Tags:#Canvas LTI integration#LTI 1.3 Advantage#Canvas Developer Key#AGS grade passback#Deep Linking Canvas#LTI OIDC JWT validation

Want to see Assignify in action?

Evaluate how specialized visual intelligence integrates with your current curriculum. Request a technical workflow briefing with our system architecture team.

Frequently Asked Questions

Common questions about grading with AI and handling handwritten student submissions.

LTI 1.1 uses OAuth 1.0 signatures and XML messages with a shared secret, and it has no standardized grade-return API or roster service. LTI 1.3 uses an OIDC-based launch flow with JWT payloads signed by Canvas's private key and verified against Canvas's published JWKS, and it adds LTI Advantage services: Assignment and Grade Services (AGS), Names and Roles Provisioning Service (NRPS), and Deep Linking. Migrating a tool from 1.1 to 1.3 requires re-registering it under a Developer Key and updating existing course-level placements.

Canvas enforces character-for-character matching between the redirect URI registered on the Developer Key and the URI the tool sends in its OIDC auth request. A trailing slash, an http versus https difference, or a different subdomain will break every launch. Compare both values character by character and update the Developer Key.

Through AGS. Enable the AGS scopes on the Developer Key, then include a lineItem object in your Deep Linking response so Canvas creates the gradebook column at content selection time. The tool POSTs scores to the line item URL taken from the lti-ags/claim/endpoint claim in the launch JWT, authenticated with a Bearer token from Canvas's OAuth 2.0 client credentials endpoint. Canvas processes scores asynchronously, so a 200 OK confirms receipt but the grade can take a few seconds to appear.

Safari and other privacy-focused browsers block third-party cookies, which breaks storing the state parameter in a standard cookie. Implement the Platform Storage postMessage fallback: use lti.put_data to store state before the OIDC redirect and lti.get_data to retrieve it after the id_token POST. Institutions that test only in Chrome on managed devices usually discover this after the first student support ticket.

Confirm a data processing agreement is in place with the vendor covering data retention limits, access controls, and breach notification, since FERPA applies to any tool receiving names, user IDs, enrollment data, or grades. Then enable only the scopes the tool genuinely uses. A tool that submits scores but never reads them back needs scope/score alone, not lineitem or result.readonly.