carnager / rofi-pass

rofi frontend for pass
GNU General Public License v3.0
699 stars 121 forks source link

OTP / 2fa support for autotype #50

Closed razem-io closed 6 years ago

razem-io commented 8 years ago

Hi,

I hacked the following into the rofi-pass script:

elif [[ $word == ":otp" ]]; then oathtool --totp --base32 "${stuff[${OTP_field}]}" | xdotool type --clearmodifiers --file -;

which enables OTP support in autotype. However I am not sure about the --base32 option. I guess most services do return a base32 code but not all. It also has an dependency on oathtools. I think this is a bit of an overkill.

If this is needed, and would be supported by this project, I would try to fix the issues I have with this solution right now and submit a PR request once I am finished.

What do you think? Awesome project by the way!

carnager commented 8 years ago

hmm, explain to me how this works. doesnt 2fa rely on the webpage you want to login to send you a key? Also: isn't the whole point of 2fa that you receive the key on a DIFFERENT device?

razem-io commented 8 years ago

OTP does not depend on the website but by definition it is a valid 2fa method. Other 2fa methods like SMS authentication depend on the website of course.

To quote wikipedia:

A one-time password (OTP) is a password that is valid for only one login session or transaction, on a computer system or other digital device. OTPs avoid a number of shortcomings that are associated with traditional (static) password-based authentication; a number of implementations also incorporate two factor authentication by ensuring that the one-time password requires access to something a person has (such as a small keyring fob device with the OTP calculator built into it, or a smartcard or specific cellphone) as well as something a person knows (such as a PIN).

The most important advantage that is addressed by OTPs is that, in contrast to static passwords, they are not vulnerable to replay attacks. This means that a potential intruder who manages to record an OTP that was already used to log in to a service or to conduct a transaction will not be able to abuse it, since it will no longer be valid. A second major advantage is that a user who uses the same (or similar) password for multiple systems, is not made vulnerable on all of them, if the password for one of these is gained by an attacker. A number of OTP systems also aim to ensure that a session cannot easily be intercepted or impersonated without knowledge of unpredictable data created during the previous session, thus reducing the attack surface further.

Tools like authy work in the chrome browser and store your OTP secrets encrypted in the cloud, and therefore can be and are also used on the same device.

Security wise it is ofc better to store OTP secrets and passwords on different devices.

I store my OTP secret together with the password. That it is why this feature would not introduce a higher security risk. Github even advices you to backup the OTP secret with lastpass or keypass.

Have a look at https://github.com/jreinert/autopass which also implements such a feature.

pigmonkey commented 8 years ago

Previous discussion of a related addition: https://github.com/carnager/rofi-pass/pull/20

Integrating something like this into pass itself seems to come up on the pass mailing list every few months, too. Hopefully something along these lines will land there if Jason has success with the hook framework he is investigating.

carnager commented 8 years ago

Well, I personally would not use it, I guess. Also there are some things to consider from what I understand:

razem-io commented 8 years ago

You do not need to store the backup keys within pass/rofi-pass. Those are only needed if you loose your OTP secret and/or device which generates the OTP. Since one already stores the OTP secret within pass the backup keys are not needed. As long as one has the OTP secret an OTP password can be generated. The backup keys should be stored in a secure location on paper or encrypted somewhere in the cloud.

With the OTP secret you can generate new time based passwords which are valid for ~30 seconds. The server and you need to have about the same time. If its off more then ~25 seconds it will most likely not work.

Since authy and google authenticator do not need the user to decide if its base32 or hex there must be a way to sort this out automatically. It might also be possible that it is always base32 encoded if you recieve a secret key. I haven't checked this yet.

Perhaps it would be possible to introduce a config setting which enables or disables this feature in the gui and default it to disabled?

carnager commented 8 years ago

autopass uses rotp to generate the one time passwords. Reading its github page it seems its only using base32

carnager commented 8 years ago

As there doesn't seem to be any interest in this anymore and I wouldn't use it personally, I am closing this for now.

razem-io commented 8 years ago

Interest is still there but time is lagging right now. I will simply push a PR when I have the time. Thank you for your time!

razem-io commented 8 years ago

@carnager What would be needed to accept this https://github.com/carnager/rofi-pass/pull/20? Python3 refactoring and then it is ok to merge?

Also is a ui integration actually needed? For me it would be good enough to have support for the autotype feature.

carnager commented 8 years ago

python3 is a must and someone needs to keep it up2date, because I wont (cant).

razem-io commented 7 years ago

Happy new year! I thought about the following solutions.

  1. Porting the #20 to python3 would work but I am not sure if it reflects the current specifications requiered (RFC 6238). Also keeping it up to date might make things complicated.

  2. Using a lib like pyotp instead. That would be easy but might add overhead?

  3. Allowing autotype to execute shell or python scripts. That would add great flexibility and reduce maintance.

@carnager what do you think?

pigmonkey commented 7 years ago

The next version of pass will have extensions. I think it is best to implement this OTP stuff using that, outside of rofi-pass. That allows us to just do something simple like:

$ pass otp github.com

And then, ideally, we extend rofi-pass to support the new arbitrary extensions somehow so that it can call pass otp or pass whatever.

razem-io commented 7 years ago

That looks great and perfectly fits my needs. However how would the syntax look like, if we need to use an extension in autotype?

Perhaps like this?

autotype: user :tab pass :enter $otp :enter

carnager commented 7 years ago

I agree. everything rofi-pass does should be possible from command line too. So using whatever pass provides sounds like a sane idea. rofi-pass could have a extension keyword extension: foobar which then calls pass foobar

Hans-Maulwurf commented 7 years ago

Is it possible to use https://github.com/tadfisher/pass-otp with rofi-pass?

carnager commented 7 years ago

Not yet, but I wanted to look into it

WhyNotHugo commented 7 years ago

A bit of a shameless plug here (I came across this since I started using rofi-pass today, and my 2fa tokens are getting in the way), but I just use totp-cli, with plain-old rofi generally and that works well enough.

Back on topic: integrating totp-cli with rofi-pass may be quite trivial; if the path matches the form 2fa/.*/code, run a different command. Some extra polishing could be to hide the intermediate directory path here though.

alexzeitgeist commented 7 years ago

In case anyone is interested, it's quite trivial to add support for the https://github.com/tadfisher/pass-otp extension, depending on how you use it. See the attached patch.

rofi-pass-otp.txt

This checks if the first line of a password entry starts with otpauth://. If it does, it rereads the entry using the "pass otp" extension, which returns the proper current otp token

WhyNotHugo commented 7 years ago

@alexzeitgeist The big downside of pass-otp, is that the pass entries take a URL-like format, rather than being simply human-readable, so it's kinda of a pain to port thing over (and adding new entries is quite non-trivial too).

alexzeitgeist commented 7 years ago

@hobarrera pass-otp uses the Key Uri Format which is quasi standard. It's exactly the content that you get when you decode the QR image (for example with qrdecode) that is usually displayed when you setup a new OTP entry. I am not sure what you consider needed to port over, but with pass-otp installed and the three lines patch I suggested, you already have full OTP integration. And when you add a new entry, all you need to do is decode the image and enter the decoded url in the pass entry.

WhyNotHugo commented 7 years ago

Yeah, that's my whole point. Rather than copy-paste a code (most providers show the code or a button to display it right under the QR), I need to somehow decode a QR code, and then input that into pass.

Personally, I think requiring that users read a QR and input that via CLI is awful UX. QRs are machine friendly, not human-friendly, and definitely not meant for users to manually extract information and paste that elsewhere.

alexzeitgeist commented 7 years ago

@hobarrera this is a one-time process. You use any tool that can decode an QR image, like qrdecode, and paste the resulting uri in a pass entry. That's all. You will never have to do that again unless you willingly reset the OTP token. How often do you add new OTP entries? I have around 20 OTP entries in my pass store, accumulated over several years, and they hardly ever change. But I can easily use pass and rofi-pass, with the integration of pass-otp as suggested in the patch, to quickly enter any OTP challenge with the same ease as entering a password. I frankly don't see any easier way.

errge commented 7 years ago

@WhyNotHugo @alexzeitgeist , can you guys please confirm whether my approach will fit both of your needs by providing the generic shell interface?

moviuro commented 7 years ago

@Hans-Maulwurf you should look at #101 which does that.

@alexzeitgeist your patch won't work in all cases, because you store a stale/old OTP value. You only need to generate the OTP value before typing; anything generated ahead of time would cause problems.

alexzeitgeist commented 7 years ago

@moviuro it does work, I have been using it since proposing the patch. What do you mean by storing a "stale/old OTP value"? My patch relies on the https://github.com/tadfisher/pass-otp extension (rather than to reinvent the wheel), which works very well. The only data that is stored is the secret OTP key in the key uri format.

moviuro commented 7 years ago

@alexzeitgeist Open your entry in rofi-pass and let 90 seconds pass. When you decide to press "Enter" to fill the OTP field, the OTP you stored (mapfile -t password_temp < <(PASSWORD_STORE_DIR="${root}" pass otp "$selected_password")) will be out-of-date. My PR avoids this issue.

alexzeitgeist commented 7 years ago

@moviuro why would I do that? I open the entry when I need to enter it in the relevant field. As you said in your previous comment - you only need to generate the OTP value before typing.

moviuro commented 7 years ago

You're missing my point: your code only works in certain conditions (for quick-typers, when you didn't reach the end-of-validty time for the TOTP value server-side). Mine should work whenever.

benhartley commented 6 years ago

Fair to say this is closed now #101 is merged?

carnager commented 6 years ago

You are correct, sir.