question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Prevent multiple user accounts with the same account id

See original GitHub issue

Today I can do this:

hoodie.account.signUp({username: 'user1', password: 'secret'})
hoodie.account.signUp({username: 'user2', password: 'secret'})

This creates two accounts with the same account id. That is a problem because GET /_users/_design/byId/_view/byId?key="<ID HERE>" will now return two results, but only the first one is used. If I sign in two the second account, my session will not be valid when using the byId view to find the account doc to validate it against.

We must prevent multiple account docs to be created that have the same account id. I don’t know what the best strategy for that could be. We might want to change how we store accounts entirely and instead of making the username part of the doc._id, we use the id instead, as the username can change while the account id cannot. We’ll have to guarantee both to be unique anyway.

ping @janl can you think of a good strategy to guarantee uniqueness of a CouchDB doc property value in a database?

Issue Analytics

  • State:open
  • Created 6 years ago
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
gr2mcommented, Jul 30, 2017

I think the we can solve this problem and at the same time prepare to properly implement custom user confirmation workflows.

What happens today

In the browser, I create an account with

hoodie.account.signUp({username: 'test', password: 'test'})

Which sends a PUT /session/account request to the server, which then creates an account in the route handler using @hoodie/account-server-api

accounts.add({
  username: username,
  password: password,
  createdAt: createdAt || currentTime,
  signedUpAt: currentTime,
  include: query.include,
  id: id
})

which creates a document in Hoodie’s users database which looks like

{
  "type": "user",
  "name": "test",
  "createdAt": "2017-07-30T03:24:45.700Z", // when account was created locally
  "signedUpAt": "2017-07-30T03:53:00.335Z", // when signed up on the server
  "roles": ["id:ow7eior"],
  "iterations": 10,
  "password_scheme": "pbkdf2",
  "salt": "1a71231d513017012313417913b1db1151fd1121fe1241fb",
  "derived_key": "a99ee677d8a59fdc4a00215b1eac68ce27428d53",
  "_id": "org.couchdb.user:test",
  "_rev": "1-6a23e40ab47bef398205241333889f18"
}

We don’t have any confirmation flow implemented at this point, once created, a user can sign in to the account. Because of that, the same user can create as many user accounts as they want, and they will all have the same "roles": ["id:ow7eior"] property.

Suggestion

When creating a user account, we store a new property createdBy which has the id of the current user. We don’t set "roles" to ["id:${accountId}"], we leave it empty which means the account is unconfirmed. We add a new method to @hoodie/account-server-api: api.accounts.confirm({id, username}). This method does two things

  1. creates a new document with the _id property set to id/${accountId}, so for the example above, it would be set to id/ow7eior.
  2. It would add set "roles" to ["id:${accountId}"] and confirmedAt to the current timestamp

Because the id/${accountId} document exists now, running api.accounts.confirm({id, username}) for an id that was already confirmed will fail with a conflict error.

I would remove the existing confirmation option for @hoodie/account-server which is currently not implemented anyway and instead replace it with autoConfirmation which defaults to true. If set to false than the developer is responsible to implement whatever confirmation routine they want. We can implement a plugin for an email confirmation flow for example, many will want to implement confirmation using Stripe and other payment providers, it’s up to them. That will also let us remove nodemailer from our dependencies which will resolve #774.

Process of implementation

  • Start a PR on @hoodie/account-server-api
    • add accounts.confirm({id, username}) method which creates the id/${accountId} and adds the id role to the user account
    • adjust accounts.add to no longer add the id role
    • update README
    • Make sure to release with a breaking change version update
  • Start a PR on @hoodie/account-server
    • update how-it-works.md
    • update plugin/README.md: remove options.confirmation and options.notifications, add options.autoConfirmation (Boolean) which defaults to true
    • Update the sign up route handler to check for the autoConfirmation option. If it is set, directly confirm the user account
    • Once the new version of @hoodie/account-server-api is released, update package.json
    • Make sure to release with a breaking change version update
  • Start a PR on hoodie
    • Once the new version of @hoodie/account-server is released, update package.json

To be discussed

  • As we now add addition documents besides user account documents, we should consider to prefix user accounts with user/, too. We might have group accounts in future as well, maybe more. This will be a breaking change which will require a migration.
  • What shall we do when an account gets deleted? Should we delete the id/${accountId} document as well or leave it there so people can’t sign up reusing an existing account id, which might be a security issue, maybe?

Anything else?

0reactions
gr2mcommented, Apr 6, 2017

Account ID can be overwritten on signIn isn’t it?

No 😃 account ids cannot be changed

Read more comments on GitHub >

github_iconTop Results From Across the Web

php - How to prevent multiple logins of the same account at ...
If you are using PHP's built in sessions feature. You can get the Session's ID using $session_id = session_id();. When a user logs...
Read more >
How do you prevent multiple user logins with same account ...
I want to be able to prevent one user sharing his/her account. I initially wanted to do it like this: Create unique session...
Read more >
How to prevent creation of multiple accounts under the same ...
I've thought of one to start with;. User uses personal mail account. You could check the domain to prevent this from happening. @companyabc.com ......
Read more >
Already logon. Then, must prevent same User Id being used to ...
Already logon. Then, must prevent same User Id being used to login. Hi. I'm not using Identity. I create my own Login Authentication....
Read more >
Prevent two users from having the same password - Super User
Assign everybody 2 passwords, one for each account. Write them on a post-it & hand one to each user so they can stick...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found