Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

accounts-password should not be case sensitive #550

Closed
acemtp opened this issue Dec 14, 2012 · 50 comments
Closed

accounts-password should not be case sensitive #550

acemtp opened this issue Dec 14, 2012 · 50 comments

Comments

@acemtp
Copy link

acemtp commented Dec 14, 2012

If a guy register with test@test.Com then he cannot log in with test@test.com but I think it should since the email are not case sensitive.

@athiwatc
Copy link

I agree with this,
Email shouldn't be case sensitive.
Username, we should be able to choose this ourself.
Password, should be case sensitive.

@drorm
Copy link

drorm commented Dec 14, 2012

No,
http://en.wikipedia.org/wiki/Email_address
The local part of an address (before the @ sign) is case-sensitive (with the exception of postmaster@example.com). The domain part (after the @ sign) is not case-sensitive.

@athiwatc
Copy link

@drorm good point, but the case that @acemtp gives is after the @ part.
(I didn't know this requirement before in my case)

@gschmidt
Copy link
Contributor

gschmidt commented Jan 9, 2013

Good catch. It definitely seems to make sense to treat the hostname in email addresses as case insensitive for the purposes of address uniqueness. Doing this correctly in general (unicode/IDNA) is quite complicated, but to start with we could handle the common case of ASCII domains.

I don't think that we should try to normalize/casefold the part before the '@' because different mail hosts handle this in different ways. Some could be case sensitive as @drorm points out. But also, some hosts also disregard periods or suffixes that start with '+' -- there's no way to know a given host's policy, so there is always the chance that a user could do multiple registrations (or enter an address in a form that we can't canonicalize.)

We would take a pull request for this (especially if it is done in a clean way rather than as a hack.) Otherwise I've added it to core team fix list and we will get to it eventually, though it might be a while.

@nate-strauser
Copy link

solution i came up with:

Accounts.createUser({username:email.toLowerCase(), email:email});

then when logging in
Meteor.loginWithPassword(email.toLowerCase(), password, ...

stores the lowercase email as the username, since the login method accepts username or email this works quite well

this does force the case insensitive email to be system unique, but that wasnt a concern for me

@SachaG
Copy link
Contributor

SachaG commented May 22, 2013

From a usability point of view, I don't think any part of the email should be case sensitive.

A lot of mobile devices automatically capitalize the first letter of any text input, meaning people unwittingly sign up with a different email address than the one they intended to use, and can't manage to log in afterwards.

We already received quite a few support emails related to this for Discover Meteor.

@brandonjschwartz
Copy link

I released a package that makes usernames case insensitive located here: https://atmosphere.meteor.com/package/insensitive-login

I left email addresses alone for the reasons mentioned above, but needed case insensitive usernames for my application.

Curious about any issues...this is my first smart package and first OSS package to the community in general.

@BretFisher
Copy link

like @SachaG I'm having the same issue on v0.6.5 with Ipad users who end up with automatic first-letter-of-email capitalized, and I agree that convention of every-site-I-know-of is that case is insensitive for email, regardless of spec. A fix in core would be awesome, but will try @nate-strauser workaround in meantime. BTW I don't use accounts-ui but do use accounts-password.

@LDubya
Copy link

LDubya commented Nov 28, 2013

Kind of a hack, but if you're using accounts-password and doing your own input validation, you can do your own case-desensitizing before adding a new user or attempting to log a user in. For example make the submitted email address all lowercase?

@mitar
Copy link
Contributor

mitar commented Jan 30, 2014

The correct thing would be to be case preserving, but case sensitive. This includes usernames as well.

@queso
Copy link
Contributor

queso commented Feb 20, 2014

@LDubya your hack wouldn't work well for sites like Github because people are particular about their username and how it is displayed.

I agree that toLowerCase() works well for email at least, but I am unsure of the best way to handle this for usernames.

@jastax
Copy link

jastax commented Mar 26, 2014

I'd also really like to have this handled differently... it's pretty annoying for iPad users.

@LDubya
Copy link

LDubya commented Apr 13, 2014

There's also the issue of multiple variations of the same email.example, these are all the same, yet meteor thinks they're different:

foobar@domain.tld

foo.bar@domain.tld

foobar+whatever@domain.tld

On Wed, Mar 26, 2014 at 3:22 PM, jansta notifications@github.com wrote:

I'd also really like to have this handled differently... it's pretty annoying for iPad users.

Reply to this email directly or view it on GitHub:
#550 (comment)

@mitar
Copy link
Contributor

mitar commented Apr 13, 2014

Those are not the same by any standard. Maybe Gmail processes them as such, but by any standard they are not. If you know of such standard, please point us to it.

@LDubya
Copy link

LDubya commented Apr 13, 2014

As far as I know gmail's practice is not standard. However the sheer number of gmail users makes this a concern. My current theoretical solution includes making additions to the accounts-password internals... However I would greatly favor publishing/using a package if one can handle this.

On Sun, Apr 13, 2014 at 2:27 PM, Mitar notifications@github.com wrote:

Those are not the same by any standard. Maybe Gmail processes them as such, but by any standard they are not. If you know of such standard, please point us to it.

Reply to this email directly or view it on GitHub:
#550 (comment)

@mitar
Copy link
Contributor

mitar commented Apr 13, 2014

I think you are confusing things here. I think that the user who registers with different e-mail accounts (even if they are on the same service and even if they end up in the same user's mailbox account after forwards and everything else) to the page probably have some reason for this. If you are trying to determine which user are doing this, this is something you yourself should do. And also think if this is maybe even a good idea. Maybe the users have a legitimate reason for that. Anyway, you can do such checks at registration time with provided hooks, or even later on determine puppets with some other measures.

But this ticket is that users would be able to login with no matter which case they use for login. So that they can use lowercase to login, but have it displayed in some other case. I do not really see that user's would register with one e-mail address (user@gmail.com) and then try to login with (user+spam@gmail.com) and expect this to lead them to the same account. And this is what you are arguing here. You probably really want just Accounts.validateNewUser.

@LDubya
Copy link

LDubya commented Jun 25, 2014

You're correct, I was confusing things.

@alanning
Copy link
Contributor

alanning commented Jul 5, 2014

Tip for those having issues with email field on iPad/mobile devices: use an HTML5 email input field.

<input type="email">

Mobile browsers will not capitalize the first letter and will display a keyboard optimized for email (has the '@' symbol front-and-center).

MDN says IE10+ supports it but we've never had any reported issues in over a year of using it with our userbase which is heavy on IE9. Just defaults to a regular text field.

@SeriousM
Copy link

I agree with this,
Email shouldn't be case sensitive.
Username, we should be able to choose this ourself.
Password, should be case sensitive.

👍 is there a way to choose it already?

@GageBachik
Copy link

+1 this seems really wierd.

@AJ-Acevedo
Copy link

Can't this be resolved with a simple str.toLowerCase();?

@mitar
Copy link
Contributor

mitar commented Dec 28, 2014

How? It should be case insensitive, but case preserving.

@AJ-Acevedo
Copy link

email.toLowerCase() should at least be implemented to solve the problem for email addresses. Usernames can continue to be another can of worms.

@doctorpangloss
Copy link

This is my top customer issue related to a meteor package right now. The vast majority of users imagine emails to be case insensitive, and the sheer number of places I have to account for this makes it a good candidate for a feature of accounts-password.

@ogourment
Copy link
Contributor

Updated my comment after doing more research. Please chime in!

The first thing to do would be add a test in password_tests.js that makes sure that user userName@domainName can login with userName@domainname.

The implementation (as @mitar pointed out) should be case-preserving (ie when displaying the user's email addresses, they should appear exactly as they were entered).
I see 3 ways to do this. The last two options make sense from a usability standpoint.

  1. userName sensitive, domainName insensitive. Two new fields required.
    • The only index-efficient way to do this might be to store the username part and the domainname parts in two new and distinct fields, since they will be queried differently. The query on username would be case-sensitive, while domainname would not. Additionally, the implementation should work for those users who do not have the two new fields. Ouch.
  2. Both userName and domainName insensitive. Additional field to store the lowercase email address.
    • When saving a user, the email address is stored in the existing field as is, and its lowercase value in a new field (lowercase_address). Login would then perform a query on the lowercase_address field.
  3. Both userName and domainName insensitive. No new field.
    • Login would use a regex to perform a case-insensitive query. It might involve a full index scan, though.

Am I missing anything?
Which one would be the right way to go?

@andreayaya
Copy link

+1 this issue needs a fix, its really frustrating for ipad and iphone users when email or username field first character is uppercase by default on the devices.

@artpolikarpov
Copy link

:—)

@jbeckton
Copy link

@mitar How did you come up with that idea? Meteor code performs the string comparison for the username. If it was not baked into the framework developers could just run their own authentication code that works as it should in many other platforms.

@mitar
Copy link
Contributor

mitar commented Jun 18, 2015

I think the issue is that MongoDB does not provide case insensitive querying or indexes. So you cannot really query a database for an user object for a username. This is the main limitation. If that would be there, then it would be easy to change JavaScript part of the code.

One solution would be to have two fields in the database. One to store username (and e-mail) in the case format user wants. And another which would be in lowercase. You would query the second one. But display the first one.

This would require change to the schema. So the question is how to do it in a backwards compatible way.

@AJ-Acevedo
Copy link

It's amazing that such a major problem has existed since Dec 2012 with no resolution. Why not just downcase the username as a stopgap solution until a better solution in finalized?

@hmeerlo
Copy link

hmeerlo commented Jun 20, 2015

I agree with @AJ-Acevedo this is quite embarrassing. It is a fundamental part of any solution. This is a production show-stopper for me.

@AJ-Acevedo
Copy link

This is a production show-stopper for me. Same here.

@SachaG
Copy link
Contributor

SachaG commented Jun 23, 2015

The useraccounts package takes care of this issue (at least for usernames, haven't checked with emails yet).

@martijnwalraven
Copy link
Contributor

I'm sorry this has taken so long, but I'll be taking a look at finally fixing this issue. There are some great suggestions about possible solutions already in these comments but I want to make sure we're getting all the input we need.

There seems to be a clear consensus that email addresses should be case preserving but be considered case insensitive for purposes of lookup. People have mentioned making this configurable for usernames, but I'd like to keep things simple if possible. Are there any good arguments against making this the default behavior for both?

As mentioned in this thread, one of the issues in fixing this is that MongoDB does not support indexes for case insensitive queries. We of course want to make sure we're taking performance considerations into account. As @ogourment mentions, a possible solution would be to do an indexed case sensitive query first and a case insensitive regex query only if no result is found. It seems like this would give us the best of both worlds without having to deal with managing an additional field.

Going forward with this change, we'd have to find a way to deal with existing users having an email address or username only differing in case. This is probably rare, but we should do something reasonable. What would your expectations be in this case?

@alanning
Copy link
Contributor

Regarding the "clear consensus to preserve case", reading through this thread I got the opposite impression. Most users seem to expect case insensitivity and are annoyed when they have to think about case. This matches my personal experience; we have always lowercased email addresses and none of our users have complained in over 2 years of operation.

Are we perhaps over-thinking this need to preserve case? Want to do a poll on the forums?

If preserving case is what MDG would like to implement, my preference is:

  • A new field to hold the case-preserved email address. The existing field stores the lower-cased value. Queries continue to search against existing field using the existing index. When email is displayed, use the new, case-preserving field.

This avoids a 2nd database round-trip, the potentially-unindexed regex query, and only the code that displays the email needs to be aware of the change. (It's @ogourment's option 2 but with usage of the fields reversed.)

Regarding how to deal with existing users with the same email address but different case, this indicates accounts which need to be merged and merging is not something that should be automated. Ideally: detect this situation, alert the developers that they need to clean their data, and let the app continue running as usual without changing existing behavior. Since this may be difficult to do: detect, alert the user, and then fail with clear instructions on how to downgrade back to previous version / behavior if wished.

@mitar
Copy link
Contributor

mitar commented Jun 24, 2015

a possible solution would be to do an indexed case sensitive query first and a case insensitive regex query only if no result is found. It seems like this would give us the best of both worlds without having to deal with managing an additional field.

I would prefer one where you have two fields, one lowercased, one in original case. And then you query by lower case, display original case.

@martijnwalraven
Copy link
Contributor

@alanning You're right, I may have overstated the clear consensus for a need for case preservation. Actually, the situation would probably be much easier if we decided to standardize on lowercased email addresses and usernames.

The reason I'd like to avoid adding new fields is because it puts the burden of dealing with two separate representations on the user. Users will have to think about what field to display or update, and this also opens up the possibility of fields getting out of sync.

@ogourment
Copy link
Contributor

I read the whole thread again; the implementation I proposed a while ago was based on the assumption that there was a need to preserve the case for email addresses. This assumption derived from @drorm citing the standard. But I tried to login to Gmail, and if I type oGourment@gmail.com or ogourment@gmail.com, not only does it find me, but it won't preserve the case. Same thing with iCloud and Yahoo! Mail (did not test with Exchange). I think we can simplify things here. @yauh made the case clear.

As for what to do for the cases where two email addresses are distinct only by case, I would offer a server-side script to be run for those interested in finding out how many occurrences there are before upgrading (then app owners should deal with them on a case-by-case basis). I would still do a test with Exchange, but would very surprised if this created problems in production.

@mitar
Copy link
Contributor

mitar commented Jun 24, 2015

I think there is a need to preserve the case for usernames. Especially because those are often displayed to the user. Maybe people spell their usernames (nicknames, handles) in various specialized ways, because they prefer that.

Moreover, while many (smart) email providers do not care about case of local part of the e-mail address, by standard it is a case sensitive part. I do think that is probably something nobody really uses in practice though.

@doctorpangloss
Copy link

👍

@martijnwalraven
Copy link
Contributor

So, we finally commited a fix for this yesterday! As this thread shows, case insensitive logins have been a longstanding issue, and people have suggested different ways of solving it. We think we've ended up implementing a relatively elegant solution, given the design constraints (such as backwards compatibility and the lack of case insensitive indexes in MongoDB). Hope you agree.

@AJ-Acevedo
Copy link

Right on! Thank you!

@BretFisher
Copy link

Great!

@ogourment
Copy link
Contributor

This looks absolutely, perfectly, fantastic. Thanks Martijn!

StorytellerCZ pushed a commit that referenced this issue Sep 18, 2021
Update nyc to the latest version 🚀
StorytellerCZ pushed a commit that referenced this issue Oct 1, 2021
None of the examples show how to import the validated method package so added this line to the first example.
filipenevola pushed a commit that referenced this issue Oct 19, 2021
Closes #550.

`loginWithPassword` now matches username or email in a case insensitive manner.
If there are multiple users with a username or email only differing in case, a
case sensitive match is required.

Although `createUser` won't let you create users with ambiguous usernames or
emails, this could happen with existing databases or if you modify the users
collection directly.

Because MongoDB does not support case insensitive indexes, we perform a case
insensitive query both before and after inserting a new user, removing the user
when we detect another matching user has been inserted in the meantime. This
leaves us with the theoretical possibility that a server crash could occur in
between the insert and the second query or remove. In that situation there
would be two accounts with a username or email only differing in case, so we
will require a case sensitive login.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests