-
Notifications
You must be signed in to change notification settings - Fork 305
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
Added case-sensitivity option for usernames #485
Added case-sensitivity option for usernames #485
Conversation
Introduced a new configuration option 'case_sensitive_usernames'. This feature allows to decide whether usernames should be treated as case-sensitive. The default configuration value is true to prevent backwards-compatibility breaks. If it is set to false, the system will convert all usernames to lowercase before storing or comparing them. This prevents issues with case-sensitive database collations, where users would not enter their email address in the exact variation used at registration. Accompanying tests and implementation have been updated or added accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure if a setting is the right solution here but let's see what @taylorotwell says.
I don't really see another option which doesn't interfere with existing applications, but I'm open for any suggestions! |
Made a few changes. Renamed configuration option to |
This is an amazing PR, it’s something I have to deal with (and remember to deal with) in applications using Postgres. However, should the lower-casing not be done before storing? Otherwise validations will fail. For example, say I have |
@martinbean good question actually. Can you weigh in here @Radiergummi? |
In the public function store(Request $request,
CreatesNewUsers $creator): RegisterResponse
{
if (config('fortify.lowercase_usernames')) {
$request->merge([
Fortify::username() => Str::lower($request->{Fortify::username()}),
]);
}
event(new Registered($user = $creator->create($request->all())));
$this->guard->login($user);
return app(RegisterResponse::class);
} The idea here is to pass the correctly cased value to any user creator implementation already present - that should work well, unless the implementation retrieves the value from the request via any other means or changes the formatting somehow (but I don't think that is very likely). Have I overlooked something here? Does that error actually crop up? Edit: @martinbean reading your question again, you were wondering whether the |
Sorry, didn’t see there were replies to this. @Radiergummi, the issue isn’t the persisting of the usernames. Yes, they’re normalised as all-lowercase in the controller. But my issue is, the validation happens before then. So, if I have |
/cc @driesvints |
Maybe we should just add lowercase validation to fortify as well like we did in Breeze? laravel/breeze#321 |
@martinbean I'm not sure I understand the problem yet; from what I've seen of the Fortify code, validation happens in the |
@Radiergummi No normalisation happens in the implementation: fortify/stubs/CreateNewUser.php Lines 24 to 30 in b5743b0
So if I try and register using |
@martinbean Ah, but we call |
Why
Using Postgres (and possibly other DBMS), comparisons are case-sensitive as opposed to MySQL.
This causes issues where users would enter e.g. Taylor@laravel.com on logging in but registered with taylor@laravel.com, and receive a bad credentials error. This bites every single installation of Fortify using Postgres.
By storing the usernames in lowercase, and converting them before passing it to user-defined authentication logic, this problem just disappears.
Backwards compatibility
I took care to not break BC anywhere:
true
for now, meaning usernames are case-sensitive by default. That way, nothing breaks for existing applications, including those with custom workarounds. It should probably be set tofalse
in the next major revision.CreateNewUser
), so no changes to existing implementations are required.CanonicalizeUsername
action can just be dropped in existing users' pipelines, if desired.