de:volt LearnLMS & SSO

LMS & SSO

Four ways to get a class into de:volt without typing thirty passwords. The first three are on every education plan; LTI 1.3 is Education Plus and site licences only.

Signing in with a school account

de:volt has no passwords at all. A student or teacher signs in one of three ways, and all three land on the same account if they share an email address:

MethodBest for
Continue with GoogleGoogle Workspace for Education schools
Continue with MicrosoftMicrosoft 365 / Entra ID schools
Email sign-in linkEveryone else, and as a fallback

Nothing needs configuring on your side for either provider: de:volt is registered as a multi-tenant app. Some tenants do require an administrator to approve a new app once before students may use it, which is the usual cause of a Need admin approval or AADSTS65004 message on the Microsoft button.

The exact steps for an IT administrator — including the OAuth redirect URI to register if your tenant prefers its own app registration, and the scopes de:volt asks for (openid, email, profile, and nothing else) — are on the school access page.

The email sign-in link always works, with no administrator involvement. If a provider button is blocked on the morning of a lesson, use the link and sort the approval out afterwards.

Restricting sign-in to your school’s domains

A class code is six characters and usually ends up on a whiteboard, so treat it as public. A school owner can require that anyone joining a class signs in with an address on one of the school’s own domains.

On any class page, under Allowed sign-in domains, enter the domains one per line:

yourschool.edu
students.yourschool.edu

Then:

  • The rule applies to every class in the school, not just the one you set it from.
  • Only a school owner can change it. Teachers see the current value.
  • Students who have already joined keep their place. The rule is checked when someone joins, not continuously.
  • A student on the wrong address is told “Sign in with your school email address to join this class”, which is usually a student who used a personal Google account by habit.
  • Leaving the field empty allows any address, which is the default.

Enter only the part after the @. A leading @ or an https:// prefix is stripped for you; anything that is not a domain name is refused rather than saved, because a half-typed rule would lock the school out of its own classes.

Importing a roster from CSV

On a class page, Import a roster takes a CSV export from your existing system and enrols those students the first time each one signs in. No code, no link to share.

File format

One student per line: email address and name. A header row is optional, and the column order is worked out for you.

email,name
ada@yourschool.edu,Ada Lovelace
lin@yourschool.edu,"Chen, Lin"

What the importer handles, because real exports do all of it: a UTF-8 BOM, Windows line endings, comma / semicolon / tab delimiters, quoted names containing commas, blank lines, and header wording such as Email Address or Display Name. Up to 500 students per import — split a larger file.

Lines that cannot be read are counted and left out; the rest still import, and the result says how many of each. A student already on the roster, or already invited to this class, is skipped, so re-uploading a corrected file is safe.

The name from the CSV is used only to fill in a student’s display name when they do not have one, so the roster and gradebook read as names from day one. A student who later sets their own name keeps it.

Seats

⚠️

An invitation does not use a seat. A seat is used when the student signs in and joins.

That means you can import next term’s roster now without paying for students who have not arrived. It also means an import can silently run out of room: if the school’s seats are full when a student signs in, they are not enrolled and no error reaches them. The class page shows seats used against seats licensed — check it after a large import.

Two further points worth knowing:

  • A student in several classes in one school uses one seat, not one per class.
  • A class must have consent attested before anyone can be enrolled into it, by roster import or by code. See Teaching.

Pending invitations are listed under the roster as Invited, not yet signed in, with a Remove control, and expire 90 days after the import.

The school’s allowed sign-in domains are deliberately not applied to a roster import: an address the teacher typed out is a stronger statement of intent than the blanket rule, which exists because join codes leak.

LTI 1.3 Advantage (Education Plus)

LTI 1.3 Advantage lets a school launch a de:volt lesson from inside its LMS, sync the class roster from the LMS, and send assignment scores back to the LMS gradebook. It is an Education Plus and site licence feature: a launch into a school on Standard is refused with a message naming Education Plus, and so is a launch into a school whose licence has lapsed. Standard schools use the roster import above.

de:volt is built against the LTI 1.3 Advantage specification rather than any one vendor, so it connects to a conformant LMS without a plugin to install or a version to match. There are step-by-step setup guides for the four platforms schools ask for most:

PlatformLaunchRoster sync (NRPS)Grade pass-back (AGS)
MoodleYesYesYes, with a line item on the activity
CanvasYesYesYes, with a graded assignment
Blackboard LearnYesYesYes, from a graded placement
Open edXYesYes, with PII sharing enabledYes, with AGS enabled on the component

Running something else? If it is certified for LTI 1.3 Advantage, get in touch and we will work through the registration with your administrator.

de:volt is the tool; your LMS is the platform. Connecting them means each side holds the other’s details, and there is no shared secret in either direction — de:volt signs with a private key whose public half your LMS fetches from the keyset URL below.

Registration

Give your LMS:

FieldValue
OIDC login initiation URLhttps://learn.devoltapp.com/api/lti/login
Redirect / target link URIhttps://learn.devoltapp.com/api/lti/launch
Public keyset (JWKS) URLhttps://learn.devoltapp.com/api/lti/jwks

Request the NRPS (names and role provisioning) and AGS (assignment and grade services) scopes when you add the tool, and attach a line item to the LMS activity you want scores to land in.

Give de:volt:

FieldWhere it comes from
Issuer (iss)Your LMS’s platform ID, e.g. https://moodle.yourschool.edu
Client IDIssued by the LMS when you add the tool
Deployment IDIssued by the LMS per deployment
OIDC authentication endpointLMS login/auth URL
Access token endpointLMS OAuth2 token URL
Public keyset (JWKS) URLLMS JWKS URL

Send those six values to your de:volt contact. We record the registration and confirm it back to you, usually the same day. Copy them exactly as your LMS shows them: the issuer in particular is matched character for character, so a trailing slash makes it a different platform.

One school can hold several registrations — the same tool deployed twice, or a staging and a production LMS — and each is identified by its own issuer, client ID and deployment ID together. A school owner can see their school’s registrations at any time to check what was recorded.

Moodle

Site administration → Plugins → External tool → Manage tools, then Configure a tool manually with the three de:volt URLs and LTI 1.3 selected. Tick the NRPS and AGS services, and set Privacy to share the launcher’s name and email — without that the roster sync has nothing to match a sign-in against.

The three values to send de:volt come from the tool’s View configuration details screen and look like:

FieldValue
Issuerhttps://moodle.yourschool.edu
OIDC authentication endpointhttps://moodle.yourschool.edu/mod/lti/auth.php
Access token endpointhttps://moodle.yourschool.edu/mod/lti/token.php
Public keyset (JWKS) URLhttps://moodle.yourschool.edu/mod/lti/certs.php

Canvas

Admin → Developer Keys → + LTI Key, entered manually or pasted as JSON. Canvas issues the client ID as the developer key’s number, and the deployment ID once the app is installed in the account (Settings → Apps → App Configurations → the gear → Deployment Id).

FieldValue
Issuerhttps://canvas.instructure.com (or your region’s issuer)
OIDC authentication endpointhttps://<region>.instructure.com/api/lti/authorize_redirect
Access token endpointhttps://<region>.instructure.com/login/oauth2/token
Public keyset (JWKS) URLhttps://<region>.instructure.com/api/lti/security/jwks

Canvas is the one platform that sends the login initiation as a POST rather than a GET. de:volt accepts both.

Blackboard Learn

Blackboard splits registration from deployment, and that changes who does what. de:volt registers the tool once, in the Anthology developer portal, and is issued a single Application ID. Your Learn administrator does not register anything — they enter that Application ID under Administrator Panel → Integrations → LTI Tool Providers → Register LTI 1.3/Advantage Tool, and Learn fetches the rest from the portal. Learn then shows a deployment ID, and that is the value to send de:volt.

Everything except the deployment ID is therefore the same for every Blackboard school in the world:

FieldValue
Issuerhttps://blackboard.com
Client IDde:volt’s Application ID (de:volt already has it)
Deployment IDShown to your administrator after deployment — send this
OIDC authentication endpointhttps://developer.blackboard.com/api/v1/gateway/oidcauth
Access token endpointhttps://developer.blackboard.com/api/v1/gateway/oauth2/jwttoken
Public keyset (JWKS) URLhttps://developer.blackboard.com/api/v1/management/applications/<Application ID>/jwks.json
⚠️

Because the issuer and client ID are shared, the deployment ID is the only thing that tells one school’s launches from another’s. A registration recorded with the wrong deployment ID does not fail — it opens a different school’s class. Check it against what the administrator sees before the first launch.

Two Blackboard-specific placement notes:

  • Grade pass-back needs a graded placement. Add de:volt through Content → Content Market (or a Deep Link) with grading enabled. An ungraded Course Content or Course Tool placement still launches and still syncs the roster, but Learn sends no line item with it, so there is nowhere for a mark to go and pass-back silently does nothing.
  • Roles. Learn sends both institution and membership roles; de:volt treats Instructor, TeachingAssistant, ContentDeveloper, Mentor and Administrator as teachers and Student/Learner as students.

Open edX

Open edX is a consumer through the lti_consumer XBlock. Add lti_consumer to the course’s Advanced Module List, then add an LTI component to a unit and set LTI Version to LTI 1.3. Studio shows the five values after the block is saved.

FieldValue
IssuerThe LMS root, e.g. https://learn.yourschool.edu — no trailing slash
Client IDShown in Studio, one per LTI configuration
Deployment ID1
OIDC authentication endpointhttps://<lms>/api/lti_consumer/v1/launch/ — keep the trailing slash
Access token endpointhttps://<lms>/api/lti_consumer/v1/token/<config id>
Public keyset (JWKS) URLhttps://<lms>/api/lti_consumer/v1/public_keysets/<config id>

On the de:volt side of the block, set Tool Launch URL and Tool Initiate Login URL to the two de:volt URLs above, and set Registered Redirect URIs to the JSON list ["https://learn.devoltapp.com/api/lti/launch"]. Open edX matches that value exactly and refuses the launch before minting a token if it is missing.

Three things about Open edX are different enough to plan around:

  • One registration per component. A plain LTI component mints its own client ID, so a course with eight de:volt lessons means eight separate registrations to exchange. Installing the openedx-ltistore plugin and using a reusable configuration makes one registration serve every component, and is worth doing before the second lesson rather than after the eighth.
  • Personal data is off by default. The XBlock withholds name and email from both the launch and the membership list unless PII sharing is enabled for the course. Launches still work — de:volt creates the account against an internal address that receives no mail — but roster sync invites nobody, because there is no address to match a later sign-in against, and students will not be recognised if they also sign in to de:volt directly. Enable PII sharing on the course if you want either of those.
  • The two services are per-component toggles. Set LTI Assignment and Grades Service to at least Allow tools to submit grades only (declarative), and Enable LTI NRPS to True. Both default to off or to the most restrictive option.

Binding an activity to a class

A launch tells de:volt which LMS activity was clicked. It cannot say which de:volt class that activity means, so each activity is pointed at a class once, when it is set up.

Launch the activity once after it is created. de:volt answers with Activity not linked and shows you the activity’s ID — send that ID and the class it should open to your de:volt contact, and we make the link. An activity can open either the class page or one specific lesson; say which you want.

Everything else is picked up automatically on the first launch, including the gradebook column scores are posted to and the roster endpoint. Neither needs to be configured by hand.

What a launch does

  1. Verifies the LMS’s signature, issuer, audience, deployment and nonce. A replayed launch is refused.
  2. Checks the school’s licence is Education Plus.
  3. Finds or creates the de:volt account for the LMS user. The same LMS user always reaches the same de:volt account, even if the school later changes the mailbox; an address that already has a de:volt account is reused rather than duplicated. A platform that releases no email still works — the account is created against an internal address that receives no mail.
  4. Enrols the user in the bound class as a teacher (LMS Instructor, TeachingAssistant, ContentDeveloper, Mentor or Administrator) or a student (Learner). Teachers consume no seat; a student does, and a launch into a school with no free seats is refused with a message saying so. A student who already holds a seat at the school does not consume a second one.
  5. Signs the user in and opens the class or the bound lesson. There is no de:volt login step.

Roster sync (NRPS)

A teacher launch also pulls the LMS course membership and turns the students in it into the same pending invitations the CSV import creates, so the seat rules above apply unchanged: an invitation costs nothing until the student signs in. Students appear on the class page under Invited, not yet signed in until then, and the class’s consent attestation still gates the enrolment.

Two deliberate limits:

  • Instructors are not imported. Adding a co-teacher grants marking rights and stays a decision someone at the school makes.
  • Removals are not mirrored. A student the LMS drops keeps their de:volt work and their membership until a teacher removes them, because an LMS enrolment edit mid-term is as often a mistake as an intention.

The sync needs an email address for each student, because that is what matches them when they sign in. Most platforms release addresses by default, and the few members who withhold theirs simply join with the class code instead. Open edX is the exception: it releases no addresses at all until PII sharing is switched on for the course, so turn that on first and the sync will have something to work with.

Grade pass-back (AGS)

When a teacher saves a mark in de:volt, the total (points awarded against the rubric’s total available) is posted to the LMS line item for that class.

Marking never waits on the LMS. The mark is saved in de:volt first and stands on its own; the gradebook post happens alongside it and times out after five seconds, so a slow or unavailable LMS cannot hold up a teacher working through a class.

Three setups send no score, all of them fixable in the LMS:

  • The activity has no gradebook column. Blackboard sends none from an ungraded placement, and Open edX sends none until AGS is enabled on the component. Make the activity graded and the column appears.
  • The student joined by class code rather than through the LMS. The gradebook row belongs to the LMS’s own user, so there has to be a launch to tie the two together. One launch is enough, and it can come after the mark.
  • The rubric is worth zero points, which leaves nothing to scale a score against.

Testing a registration

Every LMS is configured a little differently, so commission the connection once before a class depends on it. Run this checklist with your de:volt contact — it takes about twenty minutes and it is the same eleven steps on every platform:

  1. Open https://learn.devoltapp.com/api/lti/jwks in a browser and confirm it returns a key. This is the URL your LMS will use to check de:volt’s signature, so it is the cheapest thing to verify first.
  2. Register the tool, following the section for your platform above. On Blackboard there is nothing to register — deploy de:volt’s Application ID and read back the deployment ID.
  3. Send de:volt the issuer, client ID, deployment ID and the three LMS URLs, and confirm the registration is recorded against your school.
  4. Add the de:volt activity to a course and launch it once. Expect Activity not linked, showing the activity’s ID; send that ID and the class it should open to de:volt.
  5. Launch as a teacher. Expect to land on the mapped de:volt class or lesson, already signed in, with no de:volt login step.
  6. Launch as a student in the same course. Expect the same destination and a de:volt account created from the LMS email.
  7. Launch again as the same student. Expect the same de:volt account, not a second one.
  8. Check the class page after the teacher launch in step 5: every LMS student appears under Invited, not yet signed in or as a member. On Open edX, expect nobody unless PII sharing is on for the course — that is the setting, not a failure.
  9. Make the activity graded (a line item on Moodle, a graded assignment on Canvas, a graded placement on Blackboard, AGS enabled on the Open edX component), mark that student’s submission in de:volt, and check the score in the LMS gradebook.
  10. Launch from a course whose school is on Standard. Expect a refusal naming Education Plus.
  11. Remove a student in the LMS, re-launch as the teacher, and confirm de:volt does not enrol them again.

A launch that stops working at the start of a term is almost always an LMS-side key rotation — de:volt reads your keyset live, so nothing needs re-registering, but the message says “could not verify the launch” and step 3 is where to re-check. A launch that fails with Launch expired on every attempt is usually a browser blocking cookies for embedded content: de:volt carries the launch state in a cookie, and a browser that refuses third-party cookies inside an iframe throws it away. Set the placement to open in a new window or tab rather than embedded, which makes the cookie first-party and the problem go away. This bites hardest on Blackboard Ultra and in Safari, where embedded cookies are blocked by default.

Keep the results of steps 5-10 with the registration.