cosmos / cosmjs

The Swiss Army knife to power JavaScript based client solutions ranging from Web apps/explorers over browser extensions to server-side clients like faucets/scrapers.
https://cosmos.github.io/cosmjs/
Apache License 2.0
646 stars 331 forks source link

Authentication with WebAuthn #413

Open fadeev opened 4 years ago

fadeev commented 4 years ago

We're looking at more streamlined ways of authenticating with Cosmos apps (compared to importing mnemonic, generating keys, storing them encrypted in local storage).

Have you guys seen Web Authentication API?

https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API

In short, this is a built-in browser feature that allows to use external authenticators (like Yubikey) without an extension or use built-in browser authenticator module protected with a fingerprint.

Demo: https://webauthn.io/

I was wondering if we could collaborate on investigating this as potentially becoming a better alternative to mnemonic based sign-in flow.

cc @nylira @jordansexton

ethanfrey commented 4 years ago

Interesting idea and I am happy for better flows.

We had looked at tor.us support (but no code, just reviewed their docs) as Keplr has it and it seems an interesting solution.

How does webauthn compare to that?

fadeev commented 3 years ago

Missed the notification 🙂

@ethanfrey while I think distributed key generation and storage on tor.us is interesting, it still feels a bit of a lock-in and a third-party dependency.

WebAuthn has a key built into the browser. You use it so sign transactions. Can't change it, this flow assumes that an "account" has several "keys": one can be in your desktop's browser, one on your phone. Of course, having a roaming (hardware) authenticator makes WebAuthn jsut a better alternative to an extension—don't need to install anything.

ethanfrey commented 3 years ago

I like the idea, but am a bit confused about how we connect an authenticator (and also if the signatures are compatible).

Have you used this API before? Can you reference a blockchain projects (any chain/curve) that has done so?

The creation process looks quite complex/confusing: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredentialCreationOptions

And I'm not sure how it signs exactly with the get call, even after reviewing the flow: https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API#Authentication (it seems more about authenticating like password, rather than signing tx... not fully sure it can be repurposed). There is a list of algorithm ids, which does include some eddsa variants, -47 may be compatible with Cosmos SDK, but I am unclear if they are all supported.

Finally, it does seem to require a hardware authenticator connected somehow... testing the demo on Firefox gives me:

"webauthn.io wants to register an account with one of your security keys. You can connect and authorize one now, or cancel"

And the only option it shows me is cancel. :disappointed:

ethanfrey commented 3 years ago

Security Key Requirements:

A supported USB security key. WebAuthn/FIDO2 security keys from Yubico or Feitian are good options. U2F-only security keys (like the Yubikey NEO-n) can't be used with Firefox.

(https://kb.rice.edu/page.php?id=98555)

So, we need a hardware authenticator that supports the same exact signing protocol as the sdk. Is this any improvement over ledger support? I don't see the effort to support YubiKey when crypto folks are used to ledgers (with better signing support).

use built-in browser authenticator module protected with a fingerprint

This would be awesome if it works. Do you have an example?

fadeev commented 3 years ago

In-browser authenticator (biometrically accessible) for now is supported only in Chrome.

ethanfrey commented 3 years ago

I will try. But you mean chrome for mobile?

fadeev commented 3 years ago

Both on mobile and desktop.

fadeev commented 3 years ago

EOS uses WebAuthn (not saying we can use the same approach, but it's an example).

https://eos.io/build-on-eosio/webauthn-example-app/

Relevant JS part: https://github.com/EOSIO/eosio-webauthn-example-app/blob/master/src/client/wasig.ts

PR to the blockchain part: https://github.com/EOSIO/eos/pull/7421

ethanfrey commented 3 years ago

Silly me, using Brave, DuckDuckGo and FireFox mainly... I tested on Chrome for Android and the fingerprint log in was great.

Chrome for Linux asked me to connect a usb device (no fingerprint option)

fadeev commented 3 years ago

Yeah, fingerprint support on Linux may be not perfect 🙂 So maybe Chrome decided to opt out for this platform. I tested on macOS.

fadeev commented 3 years ago

The way I see it, transactions will be paseed to WebAuthn as challenges:

https://security.stackexchange.com/questions/211072/is-it-possible-to-use-webauthn-for-digitally-signing-documents-in-the-browser

fadeev commented 3 years ago

More context from Jordan:

https://github.com/cosmos/cosmos-sdk/issues/7074#issuecomment-701590182

ethanfrey commented 3 years ago

Thanks for those EOS links. I did see they use p256 curve which is NIST rather than secp256k1. Not sure if this is a limitation of webauthn, or a decision for their blockchain.

(Update: this was discussed on the SDK issue)

jordaaash commented 3 years ago

Finally, it does seem to require a hardware authenticator connected somehow... testing the demo on Firefox gives me:

"webauthn.io wants to register an account with one of your security keys. You can connect and authorize one now, or cancel"

And the only option it shows me is cancel.

This occurs when the requested algorithm is unsupported by the key you select (none support -47), or the browser doesn't support signing with a particular device (e.g. Firefox didn't appear to support signing with Touch ID when I tested, but Chrome and Safari did).

ethanfrey commented 3 years ago

The goal we want here is to generate a password in the browser and store it securely (eg. with biometrics), right?

I don't see much benefit for YubiKey support, especially with limited algorithms. And all such approaches all have some vulnerability to origin hijacking (if someone hacks the server that hosts the webapp).

Cosmjs currently allow to store mnemonics (password-encrypted or unencrypted) in browser storage (local storage or indexed db). CosmosStation has a demo using the native keychain here, which may be a more secure place to store them.

What would the benefit be of in browser webauthn over such in-browser crypto persisted to keychain? The later seems to work today in most browsers.