hoodiehq / hoodie-account-client

:dog: Account client API for the browser
https://hoodiehq.github.io/hoodie-account-client
Apache License 2.0
11 stars 24 forks source link

Prevent signIn/Up if already signed in (session exists) #154

Closed espy closed 7 years ago

espy commented 7 years ago

Currently, if the previous user did not explicitly sign out, another existing user can sign in, and will inherit the previous user’s local data. It will become part of the second user’s data, and will be synced to the server and other devices. This is Not Exactly Ideal™ :D

Steps to reproduce

Start a hoodie server

In an empty directory, $ npm init -y && npm i --save hoodie. In the package.json, add

  "hoodie": {
    "inMemory": true
  }

Start the server with $ npm start, it should run on http://localhost:8000.

Start the client

Make a new html file in a different directory, and copy the hoodie client file into that same directory. Get the client from the node_modules folder of the server you just started in the previous step, you’ll find it here: node_modules/@hoodie/client/dist/hoodie.js. Load it via script tag. Also load PouchDB, like so:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Bugsies</title>
</head>
<body>
  <script src="/hoodie.js"></script>
  <script src="https://cdn.jsdelivr.net/pouchdb/6.2.0/pouchdb.min.js"></script>
</body>
</html>

Go ahead and load this index.html in AN INCOGNITO WINDOW in your browser, for example via OS X's included python server: $ python -m SimpleHTTPServer. This will make it available at http://localhost:8080.

Triggering the bug

We'll need to create two users to demonstrate the bug, so let’s do that. Run through these steps one by one in the browser's dev console.

var hoodie = new Hoodie({
  url: 'http://localhost:8080',
  PouchDB: PouchDB
})
hoodie.account.signUp({username: 'firstuser', password: '123'}).then(dir)
hoodie.account.signIn({username: 'firstuser', password: '123'}).then(dir)
hoodie.store.add({author:'firstuser', message:'Hellooo!'}).then(dir)
hoodie.store.findAll().then(dir)

The last command should log an array with a single object, namely the one we added in the second-to-last command. Now log out with hoodie.account.signOut().

Now create the second user:

hoodie.account.signUp({username: 'seconduser', password: '123'}).then(dir)
hoodie.account.signIn({username: 'seconduser', password: '123'}).then(dir)
hoodie.store.add({author:'seconduser', message:'Ciao!'}).then(dir)
hoodie.store.findAll().then(dir)

Again, the last command should log an array with a single object, namely the one we added in the second-to-last command. Now DON'T log out, instead sign in with the first user:

hoodie.account.signIn({username: 'firstuser', password: '123'}).then(dir)

This succeeds. When we hoodie.store.findAll().then(dir) now, it will return an array with two objects, one from firstuser and one from seconduser.

Proposed fix:

Ideally, we would completely prevent signIn while there is a user session. It’s also possible to signUp while already signed in, not sure whether that also needs to be prevented.