Borealis

integration · laravel · 2023

School rosters, turned into course accounts at sign-in

A US online course provider

A white-labeled portal that connects schools and districts to an online course system through Clever. A teacher or district administrator signs in with the Clever account they already have, their roster comes across, and their students are provisioned as accounts in a separate course platform.

The operation

A US company sells online courses to schools. Those schools and districts already keep their student rosters in Clever, the identity service most of them sign into anyway.

This portal is where the two meet. A teacher or a district administrator signs in with the Clever account they already have, their roster comes across, and their students are provisioned as accounts in the course system, which is a separate platform with its own API.

It was built as a new route to market rather than as a replacement for something slower. There was no self-service path from a school roster to a course account before it existed, and the portal also captures details from educators who are still only looking, which feeds the sales side.

The part that was actually hard

One door, five kinds of person behind it. Admin, teacher, student, district administrator and district student are five separate authentication guards, each with its own model, its own table and its own session provider, and all five arrive through a single Clever callback. The code comes back, it is exchanged for a token, the identity endpoint is queried, and only then can the system work out which of the five it is dealing with. The login method branches it again, library against district single sign-on, and a first-time arrival has to be created where a returning one has to have its tokens refreshed and its roster resynced. The mapping from identity to role to guard is resolved at runtime out of a third party's response, and that is what makes it harder than an ordinary OAuth integration.

A student account has to exist somewhere else. Provisioning does not finish in this system. The student also has to be created in the course platform over its API, so the sequence runs roster sync as a background job, then a record here, then activation triggered by a teacher or an administrator, and only then the external call, carrying a payload that changes depending on whether the school or the student is paying. The identifiers that come back are stored so the two sides can be reconciled afterwards, and a failure at any step needs its own retry, its own log line and its own notification.

Two parallel hierarchies in one code base. Brands scope everything, because the portal is white-labeled. Under a brand sit schools, teachers and their students on one side, and districts, district administrators and district students on the other, each needing its own views, routes and authorization rules. Districts can also bulk-import students from CSV, parsed in the background with column validation and duplicate detection by Clever id, with the result reported by both email and a Google Chat alert.

Where it stands

Built across about ten months from 2023, and live at teacherportal.courseinstruction.com.

Different business, same shape of problem?

Every system written up here started with somebody describing an operation that had outgrown the way it was being run. If that sounded familiar, tell me how yours works today.

Talk through your version