TIL: Firebase Auth lowercases email addresses, despite SMTP
Firebase Auth stores user email addreses in lowercase, regardless of the case passed to Firebase. That can be surprising when comparing email addreseses. It's even more surprising given the risk of sending password reset emails to the wrong person.
The section of an email address before the @
symbol is the
"local-part". It's the name of a mailbox in the receiving mail system.
Mailbox names are often the same as the username of the user to which
the mailbox belongs (username@domain.tld
) but they don't
have to be. In organisations, role-based local-parts are also common
(jobs@domain.tld
) and some email providers let users choose
any mailbox name that hasn't already been taken.
SMTP specifies that the local-part of an email address is case
sensitive. This means that SomeMailbox
does not necessarily
equal somemailbox
. Each can be a separate mailbox and might
belong to different people.
Given that SMTP specifies local-part case sensitivity, it might be
surprising that I said "SomeMailbox
does not necessarily equal somemailbox
", implying
that the two might be equivalent. Many email providers do not use case
sensitive local-parts. And, somewhat confusingly, RFCs like RFC 5321
actually discourage mail systems from enforcing case sensitivity:
The local-part of a mailbox MUST BE treated as case sensitive. Therefore, SMTP implementations MUST take care to preserve the case of mailbox local-parts. In particular, for some hosts, the user "smith" is different from the user "Smith". However, exploiting the case sensitivity of mailbox local-parts impedes interoperability and is discouraged.
I get the impression that SMTP was created with the case sensitive
local-part, it began to seem like a bad idea (e.g. lots of users typing
johnsmith
when they meant JohnSmith
),
enforcement is now discouraged but the issue never actually dealt with.
Going back to the start, Firebase Auth converts user email addresses to lowercase, forcing an assumption that case doesn't matter in email addresses. That assumption is incorrect. Where a mail system does use and enforce case sensitive mailbox names, important emails like password resets will be addressed to the wrong mailbox. The person who controls the lowercase mailbox name ultimately controls whatever account is behind Firebase Auth.
I've discussed this with about half a dozen people and, so far, everyone has assumed that only a tiny number of people could be affected. That was my first thought, too, but then I realised the information available is asymmetric. Large, public email providers like Gmail don't use case sensitive local-parts in their email addresses, so there are lots of free email addresses where this doesn't matter. But what about the many mail systems run by organisations - big companies, universities, government departments? So far, I haven't found any survey of how many mail systems are case sensitive, so it's difficult to know how many people and accounts might be affected. But it's probably more than 0.
If anyone has a survey that covers enforcement of case sensitive local-parts by mail systems, I'd be interested to read it. Let me know at blog@ellen.dev
Useful things
- Cognito handles this better. In 2020 they switched the default behaviour so that new user pools are case insensitive, but that setting can be overridden. I haven't found an equivalent for Firebase Auth.
- RFC 821 is the earliest RFC for SMTP. Section 2 and the scenarios in Appendix F have language suggesting that mailbox names matched their user's name, with a simple 1 mailbox to 1 user relationship. 40 years later, things like email aliases and shared mailboxes (e.g. for customer service) have complicated that relationship.