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

Comments

Projects
None yet
@acemtp

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

This comment has been minimized.

athiwatc commented Dec 14, 2012

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

This comment has been minimized.

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

This comment has been minimized.

athiwatc commented Dec 14, 2012

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

@gschmidt

This comment has been minimized.

Member

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

This comment has been minimized.

nate-strauser commented Mar 14, 2013

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

This comment has been minimized.

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

This comment has been minimized.

brandonjschwartz commented Jun 3, 2013

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

This comment has been minimized.

BretFisher commented Aug 23, 2013

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

This comment has been minimized.

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

This comment has been minimized.

Collaborator

mitar commented Jan 30, 2014

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

@queso

This comment has been minimized.

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.

@querynaut

This comment has been minimized.

querynaut commented Mar 26, 2014

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

@LDubya

This comment has been minimized.

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

This comment has been minimized.

Collaborator

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

This comment has been minimized.

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

This comment has been minimized.

Collaborator

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

This comment has been minimized.

LDubya commented Jun 25, 2014

You're correct, I was confusing things.

@alanning

This comment has been minimized.

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

This comment has been minimized.

SeriousM commented Jul 30, 2014

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?

@gbachik

This comment has been minimized.

gbachik commented Dec 16, 2014

+1 this seems really wierd.

@AJ-Acevedo

This comment has been minimized.

AJ-Acevedo commented Dec 28, 2014

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

@mitar

This comment has been minimized.

Collaborator

mitar commented Dec 28, 2014

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

@AJ-Acevedo

This comment has been minimized.

AJ-Acevedo commented Dec 29, 2014

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

@doctorpangloss

This comment has been minimized.

doctorpangloss commented Jan 3, 2015

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

This comment has been minimized.

Contributor

ogourment commented Jan 29, 2015

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?

@ogourment

This comment has been minimized.

Contributor

ogourment commented Feb 5, 2015

I definitely tend to agree with @yauh.

Between 2. and 3., I would tend to choose 3. If there is a concern with performance, we could do a case-sensitive lookup first (faster), and only if nothing is found, try the case-insensitive (regex) query.

Thoughts?

@jbeckton

This comment has been minimized.

jbeckton commented Apr 4, 2015

Aside from passwords, any time you are comparing user input strings to values in a database that were also user input both sides should be compared as the same case whether it be upper or lower, this has been the common pattern that I have seen since I started coding 15 years ago. When email addresses or usernames are displayed they should maintain the original case but case should not be a factor when searching a db using a string to filter unless it's a password or some other authentication scenario.

At the moment I am trying out Meteor for the first time (have about 2 hours experience), I normally do not care much for frameworks that try and do everything for you and this is a good reason why. This issue has been a topic of conversation in this thread since 2012 and it still has not been addressed. Meteor may do a lot of cool things to help spin up applications quickly but since I am a software developer I require more control of whats going on, one benefit to writing your own boiler plate code is that you can tweak it when it does not work like you want it to, plus it gives a developer the opportunity to be a developer while implementing patterns and practices that one typically finds in the various layers of an application while additionally understanding why those patterns are useful.

@mitar

This comment has been minimized.

Collaborator

mitar commented Apr 5, 2015

This is less a Meteor issue than MongoDB issue.

@andreayaya

This comment has been minimized.

andreayaya commented May 1, 2015

+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

This comment has been minimized.

artpolikarpov commented Jun 17, 2015

:—)

@jbeckton

This comment has been minimized.

jbeckton commented Jun 18, 2015

@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

This comment has been minimized.

Collaborator

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

This comment has been minimized.

AJ-Acevedo commented Jun 18, 2015

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

This comment has been minimized.

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

This comment has been minimized.

AJ-Acevedo commented Jun 22, 2015

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

@SachaG

This comment has been minimized.

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

This comment has been minimized.

Contributor

martijnwalraven commented Jun 24, 2015

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

This comment has been minimized.

Contributor

alanning commented Jun 24, 2015

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

This comment has been minimized.

Collaborator

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

This comment has been minimized.

Contributor

martijnwalraven commented Jun 24, 2015

@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

This comment has been minimized.

Contributor

ogourment commented Jun 24, 2015

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

This comment has been minimized.

Collaborator

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

This comment has been minimized.

doctorpangloss commented Jun 30, 2015

👍

@martijnwalraven

This comment has been minimized.

Contributor

martijnwalraven commented Jun 30, 2015

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

This comment has been minimized.

AJ-Acevedo commented Jul 1, 2015

Right on! Thank you!

@BretFisher

This comment has been minimized.

BretFisher commented Jul 1, 2015

Great!

@ogourment

This comment has been minimized.

Contributor

ogourment commented Jul 1, 2015

This looks absolutely, perfectly, fantastic. Thanks Martijn!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment