Email addresses are not primary user identities
Monday, May 29, 2023
A lot of applications treat your email address as something immutable that is linked to you and which will never change. It can't be linked to someone else, and it can't change.
This is, of course, not true. Email addresses do change. I changed my work email address recently (associated with the same account) and let me tell you: almost no software handled it correctly.
This is the story of how badly applications handled this, how a surprising application handled it perfectly, and how you should handle this in your own code.
The mess of my email change
I've held this job for about six years, and recently announced a name change at work. Everyone has been great about it, and our IT admin immediately started helping me get my name changed across all of our internal systems.
We started with Google, so my email address would match my new name. This was easy: GSuite has a separation of email address from the account itself, and my email address was updated. My old name was setup as an alias, so anyone or any systems with the old address could still reach me.
The fun ended there, though. I use Notion extensively in my work. As a Principal Engineer, a lot of my job is writing and reading documents, after all. So what would you know when I went to sign into Notion?
It send me through the onboarding flow again! It's setup to use our Google systems as a SAML identity provider, and helpfully thought "oh hey, Nicole, nice to meet you, lemme get you an account!" The problem is, I had an account. And now there's a new, partially configured one, for this email address that didn't exist before.
What we had to do to resolve it was complete the new onboarding flow, delete the new Notion account, log out, update my Google email to be my deadname email again with an alias for my name, log into Notion with deadname email, update my email to the new one via my Notion settings (this could not be done by the workspace owner or admin, only by me as the user), confirm it via the alias forwarding to my email, log out, switch my Google account back, then log in using the usual SAML login mechanism.
Sigh. It took us a couple of hours to figure that one out and get me back in.
Then there was Slack. I was logged in still for a while, but when I logged out, and tried to log back in, I ran into that same problem: it made me a new account, gross. I don't remember what exactly we did to resolve it, but they were able to get me back into my account pretty quickly--but the new one still was hanging out. And that new one could only be deleted by the Slack workspace owner, so there were a few hours until that one was cleaned up where there were two of me.
Datadog was a fun one. We got my account updated sort of. Using username and password login instead of SSO, I could get in, but could not update my email address or name since those had been pulled in via SSO, but not updated via the same mechanism. This one had to go through their support channels to get fixed.
Myriad other systems were just like this. It was an absolute mess to figure out what exactly needed to be changed and how it would impact everything else. Apparently when my email address was updated in our HR and payroll system, it created a lot of background work, too. Not as visible to me, but it sure did screw up some systems for a hot second.
And this brings us to the unexpected hero of the hour: Jira. The software we all love to hate, but on this day, it was my knight in shining armor. When all the other accounts were like "oh hey, new email who dis", Jira just rolled with it. It noticed that I was logging in as the same identity but with a new email address, and it updated the email on my account automatically. With no fuss. And it let me know that it did it without deadnaming me, either.
Oh my god, whatever engineers at Atlassian implemented that so well: I love you, and I have mad respect for your dilligence in your implementation.
How did Jira get it right?
So, why did all these systems mess up so badly? And why was Jira's experience so smooth?
It just comes down to what they use as the primary identifier of an identity. Notion, Slack, all these systems, when you log in via SAML they use your email address as your primary identifier. (If I have to guess, this is because their systems evolved from ones that used email/password for logins, but they never broke apart that dependency.)
But that's not how SAML works. When you log in with SAML, the identity provider gives some claims1. One that it provides is the NameID, inside of Subject. This is usually something abstract, and it should be unchanging. It's a reliable way to tell if a login comes from the same person or not. On the other hand, they also include an email attribute. But this can change, and when it does... you get some weird issues if you assumed it was immutable.
What Atlassian/Jira is doing right is that they're actually using a static identifier to identify you, rather than your email address. This allows an incredibly smooth experience when any aspects of your attributes (such as email or name) change.
If you're responsible for login systems, you should decouple identity from attributes and other identifiers, since those are not as constant as you may think. Email addresses and names and phone numbers all change over time. And there's probably some security risk here, too--if you just blindly trust the email provided on the claims, I have to imagine that opens you up to some sort of impersonation attack that would be harder if you have to have the actual identity on the account itself.
Ultimately, if your system decouples identity from attributes and login methods, the entire system will be better designed and able to accommodate a better user experience. Updating attributes will be easier. Migrations of a company domain become possible. Having multiple login methods is natural and painless. Security posture improves. It's a win all around.
So please, let's stop assuming names and email addresses don't change. And if you do have to change your name and email: good luck, and hang in there.
This site has an example of an IdP response, which is helpful for seeing what data comes back and in what form.
Post notes: This one was pretty easy to write because it came from personal experience and it's something where I've seen the technical side as well. I didn't implement SAML for us but kept guiderails on the implementation as one of our senior engineers did the hard work of implementation.
But it is emotionally a little harder as I get ready to publish it. My name change is from a very personal part of me and from a recognition of my own identity. This one is baring a little bit of my soul, but through a lens of technical systems.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe to the newsletter or use the RSS feed.
Want to become a better programmer? Join the Recurse Center!