AlessioDP / kpmenu

Dmenu/rofi interface for KeePass
MIT License
28 stars 5 forks source link

Auto type username and password #3

Closed TomJansen closed 1 year ago

TomJansen commented 4 years ago

What would make Kpmenu even more awesome is an auto fill-in option, just like keepassxc has.

AlessioDP commented 4 years ago

Its already on my to-do list, currently I run a computer with Sway (Wayland instead of X11) so I was waiting for some libraries that could help me to handle the keyboard input.

When I will have some free time I will look at them again to see if I can implement it :)

ghost commented 3 years ago

It's not a library but I hope it can help https://github.com/atx/wtype

xxxserxxx commented 3 years ago

Has anyone started working on this? If not, I'll look into it.

AlessioDP commented 3 years ago

I didn't start to work on it, feel free to make a PR :)

xxxserxxx commented 3 years ago

I've been thinking about this some, and I wonder if there isn't an opportunity to do something different and possibly better.

First, I think if straight autotype as the approach, robotgo will satisfy most needs. The key sims work fine, and there are functions for getting the active window title (although it's currently broken). This would provide cross-platform functionality. However, autotype has some challenges that are evident with KeepassXC and which complicate any solution:

  1. KeepassXC uses the entry title as the window match. This leads to unsavory situations where users have to name their entries strange things to get accurate website matches, like "Login Page".
  2. Autotype fails easily when web developers decide to get creative with their login pages; this is especially problematic with Javascript abuse.

Using the entry title is an unfortunate design decision, and one that Keepass2Android gets around by having a special key/value pair with the Android intent of the app as the match. We should follow Keepass2Android and add special key/value pair containing the match expression; if the pair doesn't exist, the solution would fall back to using the entry title.

The second issue is more complex. Failing use cases leads to the KeepassXC autotype form, where users can program the autotyping, inserting pauses and tabs and other shenanigans to make things work. This requires users to learn and use a special syntax, and it's (relatively) programmatically complex as it's a macro language. Finally, it's fragile -- it is easy for the user to interrupt a more involved autotype by touching an input device. With logins that use Javascript and perform server communication between exposing fields, it can be challenging for the user to select good delay times that don't fail if the server takes a little longer to respond.

Maybe there are alternatives to autotype that would be better? Some possibilities:

The last option would be the most labor intensive, but could handle non-deterministic scenarios. Given an entry with enough keys populated, a user could (e.g.) log into a site that presents a random security question ("Name of your first pet snake") each time.

I'm most fond of the second option; it adds some user interaction, but doesn't require macro coding, and seems a fair trade-off in flexibility.

Before I go coding any of this, I'd like to get consensus on an approach. @AlessioDP, @TomJansen, @Svadkos; do you have any thoughts about this?

AlessioDP commented 3 years ago

I like the second option too but can be long to develop and make it work for X11 + Wayland.

About auto type "syntax", I would use the default behaviour, used in Windows too: use the auto type options in the entry field and follow that syntax ({USERNAME}, {PASSWORD}, etc..) & title associations.* Personally, I use a browser addon to handle the Keepass auto type.

xxxserxxx commented 3 years ago

For clarity: in these comments, when I say "attribute" I mean a KeepassDB record key/value attribute. "Field" mean a GUI text entry field.

Traditional autotype is going to add a lot of complexity, and will be nearly impossible to do well. Syncing the data is not practical. I also think the last option is going to result in much user effort, although I may revisit this at some point. Built-in browser autocomplete also struggles with some web cases, and totally fail for things that aren't web browsers, or for web browsers that don't have a plugin (vimb, surf, lynx, etc).

I think magic mouse is the best compromise, and the most interesting to me. There are a couple of different approaches to this, but the one I like the most is quasi-auto:

The user pre-defines a sequence of attributes for each record; this is much like KeepassXC's autotype macro language, but without delays or special syntax -- only an order of attributes. Once the user enters the autotype mode, there are three hotkeys: paste-and-advance; reverse; and cancel. The user clicks through the fields tapping paste-and-advance, and kpmenu pastes the value and selects the next attribute in the sequence. The reverse hotkey can be used to back-up in the sequence. If no sequence is defined, kpmenu uses the sequence: Username, Password, and TOTP (if such is configured for the record). Cancel cancels out of the mode; it also exits when the last attribute in the sequence is pasted.

The main difference between quasi-auto and traditional KeepassXC autotype is that kpmenu is not trying to tab through GUI fields -- this is left as a user activity. Controlling the UI is the most error-prone part of autotype, and also accounts for most of the complexity in the macro language and the programming thereof.

Example: User logs into gitub account configured for 2FA

  1. User chooses Log on option
  2. The Username field is already selected, or els User selects it
  3. User initiates quasi-auto mode
  4. User types paste-and-advance key
  5. User selects Password field
  6. User types paste-and-advance key
  7. Github loads the TOTP page
  8. The TOTP field is already selected, or else User selects it
  9. User types paste-and-advance key
  10. kpmenu exits quasi-auto mode
  11. User clicks Login button

Does this sound acceptable?

Alternatives

Other approaches I considered and rejected:

  1. Magic keys. Once the mode is started, map keysyms to the first character of attribute keys; U for username, P for password, C for date created, etc. <space> might open the selector to choose an attribute. Pressing a hotkey autotypes the selected attribute. The user clicks through a form pressing hotkeys. This was the original approach to magic-mouse I proposed.
  2. Selecting. Two hotkeys: P(aste) and <enter> to bring up a a dialog with the attributes. User clicks through a form, selecting fields with the mouse and attributes from (e.g.) rofi, and pressing P to paste.
AlessioDP commented 3 years ago

I think its okay, I don't think other approaches are good. Ideally I want to be able to decide what to do directly in dmenu, initially I thought that was good to add a further prompt after field selection:

I do not like to add a new prompt to decide if the user should copy or auto type the field but we can add further options for example (see at the end):

About sequences, like the Generate OTP option, we can add directly there an "auto type" button that follows the auto type sequence defined in the entry (or db).

Basically, the entry prompt:

The field prompt (Username):

The main difference between quasi-auto and traditional KeepassXC autotype is that kpmenu is not trying to tab through GUI fields -- this is left as a user activity. Controlling the UI is the most error-prone part of autotype, and also accounts for most of the complexity in the macro language and the programming thereof.

Its true that controlling the UI can be a problem, but I don't think we can actually do something, kpmenu must not read keys once dmenu is closed, this for a security reasons + non problematic Wayland support. I like to make everything configurable so tabbing is okay and we can make an option to disable them :)

Auto type a specific field (after field selection) or a sequence auto type (in field selection).

xxxserxxx commented 3 years ago

Ok, so you prefer to have more user interaction. I guess this is why there's currently no bypass to "last selected entry" -- one of my reasons for wanting autotype is because I find it tedious right now to go through the entry selection type twice:

hotkey-rofi -- "Select entry" -- -- enter -- enter (for username) -- paste -- hotkey-rofi -- "Select entry" -- -- enter -- scroll (for password) -- enter -- paste

That's 13 user actions (and more typing) to complete a login -- and that's ignoring th actions necessary to navigate the UI, and a possible password prompt to unlock the DB.

I think, though, that maybe this could be accomplished without building the functionality into kpmenu. I understand that the design prevents the client from gaining access to secrets. The reason why kpmenu has any claim to security is becaus the server is performing all of the actions -- the server calls rofi, and the server puts data into the clipboard... not the client. So there's no way for a client to access the data. That's fair.

What I'm thinking now is about writing something that essentially replaces rofi (or wofi, or dmenu) that handles the entry selection (by pop-up or window title matching), and then tells kpmenu which attributes to put into the clipboard. "AttributeS" is important because I want to reduce the 13 steps. There are fewer kpmenu changes for this; at a bare minimum, putting multiple values in the clipboard (including the OTP), and possibly calling the external program twice so that it can handle the autotype piece (either by copying from the clipboard, or getting the values passed to it the second time). The advantage to this is it keeps the critical component (kpmenu) codebase simple and auditable, but also it allows for more opportunity for adding different autotype paradigms. It also removes any responsibility for you to worry about security.

So, to summarize: I'd close this issue and open a new one that suggests adding the ability for kpmenu server to have secondary PromptPassword() mode that supports interactions with an external program that can automate more complex UI data entry.

xxxserxxx commented 3 years ago

@TomJansen would need to close this, as I can't.