near / near-wallet

Web wallet for NEAR Protocol which stores keys in browser's localStorage
https://wallet.near.org
MIT License
220 stars 176 forks source link

Two Factor Authentication (Multi-sig) #423

Closed kcole16 closed 2 years ago

kcole16 commented 4 years ago

Overview

Adding support for multi-sig based 2FA will make the web wallet more secure. This will require deploying a contract to wallet users' accounts, and will allow them to specify which transactions require multi-sig.

Stories

As a user, I want to set limits on my transaction amounts, requiring two factor authentication above the limits, so I can use the web wallet to safely store $100-$1000 worth of assets.

Flows

For any account, there are minimum three keys

1 key in localStorage 1 key in recovery 1 key on our server

TXs require 2-of-3 multi-sig

Create account with 2FA

  1. User receives Linkdrop link
  2. User enters desired account name on /create
  3. User chooses how to "Secure Account" a. Use Ledger only b. Setup SMS-based 2FA, choose email or seed phrase recovery
  4. createAccount function on Linkdrop contract is called
    1. Up to 3 keys are passed as arguments to be added as multi-sig keys a. If Ledger, only one key is passed and multi-sig is 1-of-1 b. If 2FA, backend generates a key to be added to multi-sig, returns to frontend
    2. In a batch TX a. Account is created b. Multi-sig contract is deployed, with keys as multi-sig keys c. Keys are added as access keys (separate from above) d. Account is funded (if applicable)

Sign TX with 2FA

  1. User initiates a TX, signs with key in localStorage
  2. Server sends an SMS to the user with TX details, code to enter
  3. User enters the code into the UI
  4. Server signs and sends TX

Recover with 2FA (Email)

  1. User clicks link in recovery message
  2. User is redirected to /recover-with-link
  3. Selects "Continue"
  4. Uses Sign TX with 2FA flow to finish recovery

Recover with 2FA (Seed)

  1. User navigates to /recover-seed-phrase
  2. User enters account name and seed phrase
  3. Selects "Continue"
  4. Uses Sign TX with 2FA flow to finish recovery
ilblackdragon commented 4 years ago

Specifically, I think final version of this can look:

This addresses all the attack vectors:

bowenwang1996 commented 4 years ago

@ilblackdragon what if friends collude to steal your phone 😂

kcole16 commented 4 years ago

Expanding on @ilblackdragon's comments:

Goals

Prevent attackers from

Flow

For any account, there are minimum three keys

TXs require 2-of-3 multi-sig

  1. User initiates a TX, signs with key in localStorage
  2. Server sends an SMS to the user with TX details, code to enter
  3. User enters the code into the UI
  4. Server signs and sends TX

cc @vgrichina @Patrick1904

mattlockyer commented 4 years ago

This is great. My only concern earlier when we discussed this was with:

  1. Server signs and sends TX

If it's a contract needing a second signature only, it should be fine. The server key must not have any ability to do anything except be a second signature.

Questions

What if the user needs to recover their account? Are we requiring recovery key + server key? Or is the recovery key just another version of the local storage key that we sent to them?

Lastly, because we sent them the recovery key (probably a seed phrase that recreates the localstorage key???), we probably should make certain that we've scrubbed all record of this from our servers, email servers, logs, etc... Since we technically have the 2/3 we need at some point in time. I'm still not happy about sending a recovery key in plaintext. At the very least we should throw a weak encryption around the recovery phrase based on a PIN and some client side JS.

Proposals

WRT keys to generate locally:

The second remote key:

vgrichina commented 4 years ago

What if the user needs to recover their account? Are we requiring recovery key + server key? Or is the recovery key just another version of the local storage key that we sent to them?

There needs to be 2 options: 1) normal recovery flow (recovery link key + our 2FA key) 2) gain full access when NEAR 2FA isn't accessible but you still have local storage key (local storage key + recovery link key).

At the very least we should throw a weak encryption around the recovery phrase based on a PIN and some client side JS.

such encryption doesn't add security (brute-forcing PIN is trivial unless it is unpractically long), but would degrade UX by a lot.

Note that as Illia outlined above (https://github.com/near/near-wallet/issues/423#issuecomment-623090551) in ideal security scenario there is no key in local storage / e-mail at all. However we can implement it only for mobile apps. Casual web wallet users have to accept bigger security risks, but this is fine as they aren't expected have a lot of value to start with. Once they have more value on account – we should steer users toward more secure options (mobile app, Ledger, etc).

we probably should make certain that we've scrubbed all record of this from our servers, email servers, logs, etc...

agree with this 100%, we need to make sure SendGrid/Twilio doesn't keep message bodies.

kcole16 commented 4 years ago

Two questions:

  1. Can Ledger be used without multi-sig? a. I'd say it certainly should be used without, but we'll need to account for that in the contract design
  2. We will need the user to enter their phone number. Should we remove this as an option for recovery? Or even combine the two? (Definitely tradeoffs to the latter)
kcole16 commented 4 years ago

Expanding on Create account with 2FA

  1. User receives Linkdrop link (can discuss how this works when going directly to wallet later)
  2. User enters desired account name
  3. User chooses how to "Secure Account" a. Use Ledger only b. Setup SMS-based 2FA, choose email or seed phrase recovery
  4. createAccount function on Linkdrop contract is called
    1. Up to 3 keys are passed as arguments to be added as multi-sig keys a. If Ledger, only one key is passed and multi-sig is 1-of-1 b. If 2FA, backend generates a key to be added to multi-sig, returns to frontend
    2. In a batch TX a. Account is created b. Multi-sig contract is deployed, with keys as multi-sig keys b. Keys are added as access keys (separate from above) c. Account is funded (if applicable)

cc @mattlockyer @ilblackdragon @vgrichina @corwinharrell @Patrick1904

Patrick1904 commented 2 years ago

Closing as issue is outdated