-
Notifications
You must be signed in to change notification settings - Fork 9
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
Add user passwords (#301) #308
Conversation
Hi! Thank you for looking at this. This implementation looks good to me, at least at first glance... I think the options you currently set via the command line and tillconfig module would be better off as Open questions:
|
Initially I thought it might be desired to configure stuff like this separately for different types of terminal but thinking about it now, yes, I agree.
When I was testing this I was storing them in plain text - the idea I had was that however they're stored, the function between passwords and storage mechanisms should be deterministic so that it is possible to identify a user by their password (e.g. if they forget a token, or if passwords are not issued at all, they can log in with a password alone, if enabled). We could of course also store them in plain text - which sounds bad, but I think with adequate warnings to the user could be doable...
It is - the issue is that because tokens are handled at a very low level, if tokens are presented multiple times then multiple of the password entry dialogs are shown. I need to look closer at this and work out a nicer way of solving this problem (or if you have any immediate thoughts that'd be helpful too! :-)) |
I stumbled across ui.hotkeypress() which when implemented allows us to catch usertoken events, and dismiss the dialog (which marks the end of the horrid global variable, which is nice) |
Don't worry about it - it's been a very busy time of year for me too :-) I think I've addressed all your feedback? Please have a look/play and let me know what you think. I agree about adding the UID to the login flow for password-only authentication - I've amended the PR to do this. The UID is shown in various places now, and when logging in with the password-only key, the UID is entered first (and then checked, and the shortname is shown next to it). The password hashes are now PBKDF2 (Django-style tuple storage in the database) too. I don't think I missed anything but it's entirely possible so let me know if you spot anything, or find any of it confusing/hard to use! |
Just a few notes now... In You've added Something about The I'm undecided about whether the password hash generation and checking code should be part of the In |
Also, I've just realised: if |
One more thing that has just become an issue since I checked in the sqlalchemy-2.0 migration code: all your uses of |
Thanks! Responses inline. Some of these serve me right for doing this at midnight...
I think I assumed that was a bug - whoops! I've reverted that change.
Sorted, and removed the ui.validate_positive_int() function.
Makes sense to me. user.password_check_after it is. Blank or zero values disable the check, anything else behaves as you'd expect.
I was confused until I checked my local repository and it turns out I never pushed this, which usually helps.
Makes sense, passwords.py created and the hashing and checking logic moved in there.
Sorted.
I've changed it so if force_password_registration is disabled, blank values are accepted and clear the password. Do you think people with the edit-user-password permission (managers) should always be able to clear user passwords, irrespective of the force_user_passwords setting? It could be useful, as if a user forgets their password they could just have it cleared, and then set their own the next time they log in to the till. That way, the manager doesn't know the password - but then again, the user could also just key it in when required as they are being edited...
All done. |
Yes, I think people with permission to edit other users' passwords should be able to set them to blank, so the user is forced to set a new password next time they visit the till. I think the logic around when to check the password still needs some thought. For example, starting with a till database with no passwords set at all I did the following:
We have three timestamp fields to think about:
I think The check in It's generally not necessary to call |
That makes sense - sorry, life and things sort of happened between starting this work and coming back to look at it in the new year and so it has taken me a while to get back up to speed with what I actually did! I have refactored user.py and removed The I've tested this in a few scenarios and combinations of settings and it appears to work - although I don't actually own anything that can read tokens (despite having about n+1 iButtons and RFID things...) so I am limited to debug -> fake token. Also, I removed all the instances of |
I got a "force set password" prompt in testing, despite I think the logic for this would be clearer if it was all implemented in I think You dismiss the password prompt popup if a new usertoken is presented before the password is entered, but you don't dismiss any of the others like the password setting popup and the prompt for setting a new password. I was able to stack these arbitrarily deep by presenting usertokens in sequence with no password set! I don't think the popups for setting a new password at login should be un-dismissable — the user should always be able to back out with the Clear key (although they would end up not logging in). Having a box stuck on the screen will make users panic and say "the till is broken". When checking the password, it would be nice if the user didn't have to press Cash/Enter after entering a correct password. You could use the same technique as |
(Maybe make a mixin class for "dismiss this popup when a usertoken is presented or the LOGIN key is pressed", with the |
I've just made what I hope is the final release in the v23 series. If it's ok with you, I'll merge this pull request, fix up the remaining issues, fix some other unrelated issues that require simple schema changes, and get ready for a v24 release. |
Hey - sorry it's been a while, I've not had much free time recently! Feel free to take/update/merge - let me know if you'd like me to do anything/have any questions. |
Here are the changes I made after merging the pull request: bc06249 The changes from v23.15 to that commit (i.e. the whole feature as introduced) are here: v23.15...bc06249 Next time I get a chance to look at this, I'll add the remaining features I think are needed: avoiding the need for the user to press Cash/Enter on password entry, a plugin system for different password hash algorithms, and support for changing passwords through the web interface. Thank you very much for your contribution! I don't think I'd have got around to implementing it nearly as quickly without your help. |
Fixes #301
This PR adds passwords to users and if the right config values are set, prompts them for their password when they use a token they have not used for a while. If configured, users will be forced to set a password upon login if they do not have one already.
It also allows users to login directly with their user ID and password, if the configuration option
user:allow_password_login
is enabled. To support this, in any case, the user ID is surfaced a few more times around the UI, namely in the edit user dialogs and on the current user information dialog.Passwords are PBKDF2 hashed + salted with the necessary information to check them stored in the database. This means alternative hashing methods or implementations could be added without breaking previously-set passwords.
Passwords can be changed by anyone with the
edit-user-password
permission (manager
s by default). Users can change their own passwords, but only if they have theedit-current-user-password
permission (whichbasic_user
s do by default).