When I first built Liszt, it required (logically) that users have a username and password. Well, more correctly, it required that I have a username and password, since I was the only one using it. As it grew and I got better at programming, I kept slightly upgrading the credential process and permissions system–the last iteration used a salted password based on a proprietary hashing algorithm.
When storing usernames and passwords, the worst way to go about it is to store passwords in plain text. If your password is “password”, then you just put “password” in the database. Hashed passwords are a little better. It involves taking a one-way Hash, which is a way to take a variable length string like “password” or “pwd” and maps it to data of a fixed size, like 36 characters. The problem here is that if multiple people have the same password, if a bad actor were to steal the User database in Liszt, they could cross reference hashed passwords with password hints.
Liszt never had password hints though, so…but whatever.
Encrypted passwords are alright, but since encryption has a sibling named decryption, it’s safe only as long as the encryption key is safe.
The safest way to store passwords oneself is to combine the user’s password with what’s called a salt. In the case of Liszt, I took a hashed combination of the users ID number, combined with a hashed combination of the user’s password, hashed the result for good measure, and saved that in the database. That way, even if everyone had the same password, it wouldn’t show up in the database as the same password. Everyone gets their own gibberish.
Much of my philosophy on how to properly authenticate users comes from YouTuber Tom Scott–most specifically, his “How Not to Store Passwords (https://www.youtube.com/watch?v=8ZtInClXe1Q, which I’ve just explained in brief) and “The Fictional Day Google Forgot to Check Passwords” (https://www.youtube.com/watch?v=y4GB_NDU43Q). And as I onboarded more and more students, it made more sense to start using alternative providers–Since most clients used Microsoft Office 365, having Microsoft handle the authentication made the most sense. That way, I never have to deal with the passwords.
I wrote much of the code to handle the OAUTH login myself, based on snippets I found online and bolting them to Liszt’s Single Sign On system. Liszt doesn’t use external frameworks for the simple reasons that 1) They either didn’t exist and I wasn’t smart enough to use them when I get started, and 2) It would be a massive undertaking now, and Liszt is kind of its own platform. Because of this, I didn’t use a lot of third-party libraries.
In late 2020, I finally integrated the PHP package manager Composer because I needed it for some storage work I was doing (maybe a blog post in there too), which opened up the possibility of using some existing packages and modules I previously either didn’t use, or integrated manually. One of these things is the League of Extraordinary Packages’ OAUTH Client.
At the beginning of 2021, Liszt contained four login systems. The first was the original Liszt username/password combo, the second was Microsoft 365 for registered users, the third was Microsoft 365 for students and clients, and the last was
A hacked-together beta version of the Google OAUTH code, which worked fine on the Google end, but I never really properly wrote the Liszt end. My work in January has been to reduce Liszt to one login system that can handle multiple providers. Which is…really what I should have done at the beginning.
This sounds reasonably simple, but here are some of the challenges:
The Liszt Login code is one of those things that I play with every couple of years, and as long as it works, I don’t question it. So the code–which does a lot of things including allowing for cross-domain logins (logging into Liszt automatically logs you into Liszt Swipe, Liszt Studio (defunct), Liszt Account Management, ScoreShare, AudioAtlas, and anything else that uses the Liszt login system). This is…pretty hairy.
Liszt accounts and Liszt student/client accounts are totally separate entities, and it’s possible to have access to both. And what’s more, it’s possible to have access to multiple client accounts. Undoubtedly what would happen is that a student would try to log into Liszt instead of the Liszt Portal, and then that ends up being an email.
There’s no onboarding process for Liszt, and only a rudimentary one for Liszt Portal.
There’s also no account sign-up.
Also, I wanted the following:
I wanted the ability to add service providers (Google, Apple, etc.) later.
I wanted the ability to have a third class of authentication–There are registered users, there are registered clients, but I also wanted a basic identity provider–unregistered visitors. People who might need to be authenticated in some way, but I don’t need a full account for. I call this “fingerprinting.”
So there’s just a ton of access control flow going on. Here’s what that looks like now.
For starters, when I coded the original Liszt Office 365 login setup, I used my personal email account. Since we’re upgrading, I moved it to NoteForge. Sound easy? Yes. Is easy? Microsoft now requires that commercial or business accounts be verified, which is a reasonably straightforward, though undocumented process. What that ultimately means is that instead of this:
Liszt now asks for permissions like this:
Even though it’s the same app, in the view of Microsoft it’s different, so all users will have to re-authorize Liszt. Only this time, it comes with a nice blue checkmark.
So Microsoft (or Google or whoever I end up using as providers) verifies the login–Liszt never sees the password or login information, it just gets Profile information, who you are, what your email address is, etc. Then Liszt has to figure out what to do with you. And that flow is, simply, complicated.
The most straightforward cases are either registered users or identified clients/students logging in–It just passes the info on to the appropriate part of Liszt. Next are users or clients who haven’t logged in before and need their Microsoft username applied to their Liszt profile. Reasonably simple.
What about Clients who are trying to log in as Users? Or vice versa? Now Liszt tries to nudge you in the right direction:
Alright, we have those. Next up are people who are clients in multiple Liszt sites–which are arguably few, but better to take care of this now while I know what the code does. If you’re logging in at the wrong place, Liszt will now try to nudge you towards the right client site.
At NDSU, we tried allowing students to self-enroll in 2019, and that worked really well. But, it was a completely manual solution. As in, I wrote some code that said “enroll at this website, get attached to the Marching Band.” With this system, I’ve built in hooks to allow students to self-enroll by inputting a code, which will grant them the appropriate access and assign them to the appropriate groups. That’s not hooked up yet, but it’s ready to be written.
People who are logging in who just need to be fingerprinted? That’s easy–since we’re not checking them against a database, we just package their data and send it to the appropriate Liszt-built system.
Finally, there’s the user onboarding flow, which is designed for creating new registered user accounts. That group will either want to get access to an existing site, or to create a whole new site. That last group, I’m not ready to automate yet, so Liszt collects their information and creates a workorder. Those new users to an existing site, however, now get the option to type in a secret code (provided by the administrator) which creates a permissionless user for that site. Admins can go in and assign the required permissions afterward.
Complicated? Sure. Better in the long term? Way better. In fact, I coded the Google login code for the system in about ten minutes this morning.
Progress? Very yes.
The new version of the Liszt login system goes live later this week.