Prevent multiple user accounts with the same account id
See original GitHub issueToday 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:
- Created 6 years ago
- Comments:8 (7 by maintainers)
Top GitHub Comments
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
Which sends a
PUT /session/account
request to the server, which then creates an account in the route handler using@hoodie/account-server-api
which creates a document in Hoodie’s users database which looks like
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 theid
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_id
property set toid/${accountId}
, so for the example above, it would be set toid/ow7eior
."roles"
to["id:${accountId}"]
andconfirmedAt
to the current timestampBecause the
id/${accountId}
document exists now, runningapi.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 withautoConfirmation
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 removenodemailer
from our dependencies which will resolve #774.Process of implementation
@hoodie/account-server-api
accounts.confirm({id, username})
method which creates theid/${accountId}
and adds the id role to the user accountaccounts.add
to no longer add the id role@hoodie/account-server
how-it-works.md
plugin/README.md
: removeoptions.confirmation
andoptions.notifications
, addoptions.autoConfirmation
(Boolean) which defaults totrue
autoConfirmation
option. If it is set, directly confirm the user account@hoodie/account-server-api
is released, updatepackage.json
hoodie
@hoodie/account-server
is released, updatepackage.json
To be discussed
user/
, too. We might have group accounts in future as well, maybe more. This will be a breaking change which will require a migration.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?
No 😃 account ids cannot be changed