Lower-case email in Users table before comparing with email at login

Hi,

If you put an email in upper case in the users table, Anvil will not let you log in with that email in lower case. The opposite case works.

If you copy and paste email addresses from Outlook directly into the Users table, you will typically get the emails in upper case.

If both the email from the Users table and the email from the login were lowercased before being compared, this would never be a problem.

Please consider doing this change.

Here is an app with an upper case email in the Users table. Try to log in lower case (password ‘test’). https://anvil.works/build#clone:TUL5A4FNJ7RSB27Y=3RFPZFWZKDI55OSIFS2BLFWD

Best regards,
Stein

There’s a good, historical reason for this. I was there when it happened. This is how I remember it:

Anvil’s login names were originally case-sensitive. This adds security, by making it harder to brute-force guess a name.

However, most login names were email addresses. For historical reasons, email addresses, as used elsewhere, are case-insensitive. So not all users were careful about how they entered them. To accommodate these users, Anvil made a special case: if the login name is entered in all-lowercase, then it is treated as case-insensitive.

The result: Each user can have it their own way. Those users who want to have case-sensitive log-ins can do so. Those who don’t, don’t have to.

This, too, is a feature. It’s in the forums, but I haven’t seen it in the documentation.

And it’s under your control, right now. If you want to brute-force rewrite all your login names as lowercase, in your Users table, you can do so in a short (under 10 lines) Server Module function. Call it after pasting in a series of addresses, and you’re good to go.

I would prefer that this be 1) documented and 2) controlled via explicit flags. But for now, I would use this short, easy workaround.

1 Like

Hi @stein,

@p.colbert has the history right! (My goodness – we’re old enough to have history now :wink: )

Because case-insensitive comparisons are expensive, we do exact-match lookups on the Users table. If you enter Stein@example.com in the login form, we search the Users table for the string and its lowercase equivalent – so:

  • stein@example.com (lower-case)
  • Stein@example.com (original case, for compatibility with existing mixed-case tables)

All the built-in functions (signup_with_email() etc) lowercase the email before storing it in the table, which makes all logins case-insensitive. If you’re building your own sign-up or enrolment process, I’d recommend you do this too.

It might be nice to flag this in the Users Service editor, or even automatically lower-case when you paste the address in – that would prevent you from being caught out like this! I’ll also make a note to make our documentation more clear about this behaviour.

In the meantime, as @p.colbert says, the fastest route for you is probably a quick script, in a Server Module or the Uplink, that goes:

for user in app_tables.users.search():
    if user['email'] != user['email'].lower():
        user['email'] = user['email'].lower()
4 Likes

@p.colbert and @meredydd,

thanks for the explanation and the bonus history lesson!

I’ll lower-case my Users table. I think it is a good idea, as you propose, to flag this behaviour in the Users Service module.