-
-
Notifications
You must be signed in to change notification settings - Fork 529
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
Passwordless login #14351
Passwordless login #14351
Conversation
I fear I can't work on that failing 7.2 test... seems not to have something to do with my code changes? |
Travis uses PHPUnit 8 for PHP 7.2, that's why it's failing. We should merge the Travis config from 2.x into 3.x |
Added screenshots of the changed login screen and magic link email... |
$this->setPlaceholder('onManagerLoginFormPrerender', $eventInfo); | ||
|
||
$hour = date('H') + (int)$this->modx->getOption('server_offset'); | ||
if ($hour > 18) { | ||
$greeting = $this->modx->lexicon('login_greeting_evening'); | ||
} | ||
elseif ($hour > 12) { | ||
} else if ($hour > 12) { |
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.
Why did you add these code style changes? Seems unnecessary (and not an improvement, but I know code styles are very subjective)
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.
@wuuti Please use elseif
instead of else if
, since you could write:
if ($a) {
// code
} elseif ($b) {
// code
}
instead of:
if ($a) {
// code
} else {
if ($b) {
// code
}
}
If we use an autoformatter (with some strict rules) in 3.x, the second code would be generated.
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 reverted any code style change (accidentally autoformatted by my IDE).
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 like the idea, but the implementation isn't quite ready yet. Based on a code review I've left a bunch of inline comments on specific things that should be addressed. Some of my comments may come from a lack of understanding/misunderstanding on my part in which case please do correct me.
As an aside, should this be called a "magic" login link? I like magic, but that doesn't seem like the kind of terminology the MODX core tends to use, and this is a very in-your-face type functionality that users interact with, so it's worth discussing what the exact terms we use to describe things. I'd personally drop the word "magic" and use only "login link".
} else { | ||
$this->setPlaceholder('success_message', $this->modx->lexicon('login_user_err_nf_email')); | ||
} | ||
} else { |
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.
This else
is exposing an enumeration vulnerability allowing valid (registered) emails to be bruteforced.
To avoid that vulnerability, the response has to be identical for users that exist and users that don't. Ideally it also needs to account for the processing that happens when a user exists (parsing a message, sending an email), ensuring that timing can't be used to distinguish between a successful/failed attempt.
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.
Ideally it also needs to account for the processing that happens when a user exists (parsing a message, sending an email), ensuring that timing can't be used to distinguish between a successful/failed attempt.
I guess the same should apply for regular logins and password resets?
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 think it's not necessary for logins as there's either a failure or success, plus user-level brute force protection, and IIRC we addressed the difference between "user does not exist" and "password for user is incorrect" in 2.6 or so.
For password resets, yes, same protections need to apply there, but IIRC that was already addressed for 3.x when the password reset was reworked.
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.
Both cases now return the same message to the login frontend.
Regarding the timing, how would you expect that to be implemented? Timing difference is minimal and processing varies a lot here. It might be possible to sleep the processing so that both e.g. take the same 1s to respond. But is that what we want here? Or just add random 200-500ms to the process? Still it depends on the connectivity when sending out the mail... it might take longer to send out an email (shouldnt, but...)
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.
@wuuti Here's an article that deals with the varying ways to prevent timing attacks: https://blog.ircmaxell.com/2014/11/its-all-about-time.html#An-Actual-Delay-That-Works
1d5db8d
to
9edd6e3
Compare
I tested and have a few comments:
The “magic” link is sent to the mail, and everything works, it seems, but there are errors with the login:
And now I can not enter the manager panel in the standard way :) |
Merge remote-tracking branch 'upstream/pr/14351' into 3.x * upstream/pr/14351: Changed registry topic. Removed unused code. Refactored. Adjusted lexicons. Remove legacy code. Reverted unwanted code formatting. Changed email string. Make magic login link work. Added first system settings for magic-login-links.
Mucho gracias, @wuuti. Love this functionality. In the merge I've resolved some conflicts and made a couple of small tweaks.
|
What does it do?
This adds the functionality of sending of a magic login link (like slack or notions do) to get you logged in to the manager instead of username/password for login.
Why is it needed?
To log in with username and password has some drawbacks:
The magic login link solution solves these problems without introducing less security (everything depends on the security of the users mail account, as with password recovery currently). Instead, we get an even better security level, as we don't need to store/exchange passwords any more and do not force our users to 'create' and remember a difficult password.
How does it work?
The function is activated by a system setting. Once you have that activated, the login screen changes to an email-only input field. After submit a one-time login link is emailed to the users mailbox if there is an account with that email address in the manager.
Internally the code just "reused" the existing password recovery functionality, so no new processors are needed here. Every time a valid login link is used, we set a temporary, random password and directly use that password internally to login via the existing processor. The links are usable only once, and have a small, configurable expiration time (default: 3600s).
Possible improvements
Note: this is an outcome of the MODX meetup in Engelberg@Grünenwald. It started as a POC, but we realized quickly that we don't need to change a lot of the existing code, as everything was already there in the recovery functionality.