-
-
Notifications
You must be signed in to change notification settings - Fork 839
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
Refactor password checker, add extender #2176
Conversation
if ($result === false) { | ||
return false; | ||
} elseif ($result === true) { | ||
$valid = true; |
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.
What's the benefit of not immediately returning false here. In any future iteration the value will only be set to true if true anyway. Allowing more iteration will only cost us performance here.
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.
Do you mean returning true? It's because an output of false overrides any outputs of true, regardless of order of evaluation. Unless order is a feature (as with middleware), I'm trying to maximally avoid order of evaluation mattering.
As such, an explicit false, denies, an explicit true allows as long as there are no explicit denials, and no trues means deny.
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.
So if I understand correctly, we need at least one return to be === true
and none === false
for checkPassword
to return true
.
I'm assuming it's so checks can return null
without impacting the result if they have neither success nor failure.
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.
To clarify, checkers should return as follows:
- If the password is valid, return true
- If not, return null
- If the request must be blocked, return false
This is what's currently used in Clark's extensions. Before I merge this in, is this schema fine with everyone?
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.
Maybe we could offer CONST aliases just like we did for policies? I'm ok with the raw value, but maybe it would be a bit easier in the documentation if each of these option had a human readable constant associated with it?
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.
Hmm, I'm not sure. They'd have to be properties of the User object. More importantly though, I have no idea what to call the null
one. User::PASSWORD_VALID
and User::PASSWORD_INVALID
make sense, but maybe User::PASSWORD_SKIP
?
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.
Not sure 🙃
Maybe I'd call them something including AUTHORIZE, FAIL_AUTHORIZATION and something with PASS/SKIP/NEXT?
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.
Also, technically you don't really need to return null
ever. It's also what happens when you don't return anything so there might not be a need for a constant.
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 that this might make things more confusing to be completely honest. Let's keep it as is for now; if we see confusion in the developer community we can always add aliases later I think?
Also, technically you don't really need to return null ever. It's also what happens when you don't return anything so there might not be a need for a constant.
True, I'll try to clarify this in the docblock
376389a
to
c845154
Compare
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.
Code looks good, mostly. Thanks!
On a higher level: This feels a bit too oriented around the old event, but I'd like us to focus on use cases with the extenders. What are we (extension authors) hoping to achieve when using this extender? Doesn't changing the password checker usually mean we'd need to change the hasher as well? We might need an abstraction around this combination of actions: persisting and checking passwords. (PHP's password hashing abstractions also adds a rehash check to the mix.) |
Well, I'd agree with that point. This reminds me most of Django's authentication backends: https://docs.djangoproject.com/en/3.0/topics/auth/customizing/. We could expand the scope of the extender to entail that? |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. We do this to keep the amount of open issues to a manageable minimum. |
Shoo! |
fb6570e
to
e800105
Compare
@clarkwinkelmann The only examples of real-life use of this event are in your extensions, so congrats, you're hereby subpoenaed as an expert witness 😛! I agree with Franz that the password checker and hasher are related concepts. But from what I'm seeing in https://github.com/clarkwinkelmann/flarum-ext-passwordless/blob/230ef8a5602bb4a72a25a42f50823d142d44f932/src/Listeners/CheckPassword.php and https://github.com/migratetoflarum/old-passwords/blob/d6b78d2ac6cd609d41e5df1af69c548bcda920f7/src/Listeners/CheckPassword.php, it's not quite that direct. IMO, we have a few options:
When it comes to the evaluation logic, I'm fine dropping the "priorities of approve/deny" if we replace this to use |
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.
Indeed, seems like I'm the only one to have attempted to extend this.
One use case is definitely replacing the default hasher. But this is probably a rare use case, since the default is very sensible.
On the hasher front, I'd suggest the following, if that's not already the case: allow customizing the hasher of the Laravel Hash object with a config value (assuming this is customizable with a constructor parameter), and have the hasher in the container (that's already the case).
This offers a lot of flexibility and an extension can always replace the hasher in the container if they wish so. No need to build any extender or configuration UI for the password hasher IMO.
The other use case is the one I have used in these two occasions: allowing additional things to be used as password, which aren't in the password
column, and possibly not in the database at all.
I think the proposed solution in this PR looks good. I don't think we really need priority to be customizable. Ability to add and remove should be enough. Having the default check be in the stack also allows extensions to use this path if they want to replace the default hasher with something that's not plug-and-play into the Laravel Hasher.
[ci skip] [skip ci]
b43864f
to
8911e81
Compare
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.
Any reason ContainerUtil::wrapCallback
is called in the provider and not in the extender? Are we consistent across extenders with that way of doing things?
@askvortsov1 was something holding this back? Should I do a final review now or wait for something else? |
I don't believe so, should be good to go |
Merge conflicts resolved, this should be good to review. |
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 have not tested locally, but it's looking all good to me.
I'll try to update my old-passwords extension before release to actually test it with the new system once this is merged to master.
I think you will want to update the deprecation comment before merging? It's the only thing I noticed.
Part of #1891
Changes proposed in this pull request:
Reviewers should focus on:
Confirmed
composer test
).