Userbase is a tool for developers to build secure and private apps. We launched 1 year ago [1], and have worked hard to widen its use cases. Userbase offers built-in user accounts and authentication, an end-to-end encrypted zero-management database, file storage, streaming and sharing, and logic to process and manage subscriptions (via Stripe). All Userbase features are accessible through a simple JavaScript SDK, directly from the client. 100% open source, and all platforms are supported (browser, iOS, Android, desktop).
Today, Userbase can be used in apps that don’t require end-to-end encryption, for those who like that Userbase can handle authentication, data storage and real-time syncing in a few lines of code.
We also completed a security review by an independent team [2], and wrote up a comprehensive specification of our architecture [3].
Personally I joined in working on Userbase to store end-to-end encrypted data in a performant way for an accounting app. Under the hood, each write to a Userbase database is an append-only transaction to a log stored in DynamoDB (therefore constant time), which is then pushed to connected clients over a Web Socket. Each client then decrypts and applies this transaction to its local state of the database in memory (real-time syncing is provided out of the box). In this process, the server ensures each client receives transactions in a consistent order, 100% of the time. This is unlike some of the (very awesome) decentralized alternatives that exist today (OrbitDB, GunDB, Scuttlebot), which generally rely on CRDTs to stay in sync, and CRDTs can be pushed in any order. For certain applications, the consistent ordering guarantee a central server provides may be extremely useful (such as in an accounting app), on top of the added reliability and performance.
>First, the client makes an unauthenticated request to the server to retrieve the password salts associated with the username. If no user is found, an error is returned to the client. If a user is found, the server sends the client the user's password salt and password token salt, which the client uses to rebuild the password token. The password token is then passed to the server for authentication. To prevent brute force password guesses, clients get 25 incorrect attempts in a row before the server locks the user out of their account for 24 hours (Note we are aware this introduces a DoS vulnerability. Our first priority is to protect user data. We plan to implement a more sophisticated lockout mechanism in the future).
Hang on, so the process of retrieving the salt gives the remote client information about whether the user exists? Doesn't this mean that an attacker could take a list of possible usernames, and confirm which of them are using your service?
Seems like you could return a salt even when the user doesn't exist, and that would prevent this information disclosure.
Userbase is built on the assumption that in the event an attacker compromises the Userbase server and database, the attacker would not be able to access protected user data. We chose this assumption to build on because we figure that users and developers alike should assume that data stored at rest in cloud-based databases will eventually be leaked, as we've seen countless examples at almost every major company. Thus, we figured the default assumption is that usernames would not be expected to be private (and so yes, to answer your question, user enumeration is currently possible).
Additionally, practically defending against user enumeration beyond rate limiting sacrifices a level of security and privacy (for example, by requiring users provide an email to sign up to your service, or through some other means that likely ties the user to an identity and storing this in our database in plaintext), rather than allowing them to use pseudonymous usernames alone.
While we do recognize username enumeration is an issue (because users tend to reuse passwords from other sites, or don’t want to be found out using a site), we concluded that properly defending from user enumeration by default would have too material of a negative impact on user experience for little gain on top of what we already provide in way of protecting user data, and instead focused on defending against potential follow-up attacks by limiting brute force login attempts, and recommending that you tell your users to use a password manager at sign up.
The most significant place defending against enumeration affects is during sign up. When a user’s account already exists, we say the username is already taken, which isn't possible when properly defending against enumeration.
We're planning to allow you to enable email verification in your app if you want to, so users will need an email to successfully create an account. Once that's in place, we'll defend against enumeration more concretely. There are other places in addition to the salt retrieval that would be modified in similar fashion. For example, password reset will need to always successfully return even if a user provided the wrong username, and sharing a database with another user will always successfully return even if the other user doesn't exist (e.g. from a typo).
Just rolled my own auth...yet again. Next time, I’m using this. Been following Userbase since it was first announced and it is now at a point where I’m comfortable using it on a project. Nice work!
Would e2ee really be guaranteed if a user sets an 8 char password? Because if so an attacker with control of the server could brute forcedly decrypt the encryption key, and in turn all DB contents for a user, no?
Apologies if this is covered somewhere in the docs, but I couldn’t find it.
We use scrypt for password hashing. From the scrypt paper (which keep in mind is assuming hardware from 2002, and isn't assuming an attacker is using ASICs which have been developed since then), the estimated cost of hardware to brute force guess an 8 char password in 1 year is $4.8 million with our chosen parameters. [1]
Ultimately we strongly recommend that developers using the end-to-end encryption mode of Userbase recommend their users use a password manager, since losing their password means losing their data (and we try to make this extremely clear to any developers using Userbase via the admin panel and docs). A password manager randomly generating passwords makes this a non-issue.
But alas, we do recognize not everyone will, which is where scrypt comes in to play.
Can this be self-hosted, or does it depend on a 3rd party service? I am extremely anxious about depending on a company that could go out of business, or maybe even worse, acquired by someone else and subject to bait and switch price rises, and the data privacy issues.
j-berman|5 years ago
Userbase is a tool for developers to build secure and private apps. We launched 1 year ago [1], and have worked hard to widen its use cases. Userbase offers built-in user accounts and authentication, an end-to-end encrypted zero-management database, file storage, streaming and sharing, and logic to process and manage subscriptions (via Stripe). All Userbase features are accessible through a simple JavaScript SDK, directly from the client. 100% open source, and all platforms are supported (browser, iOS, Android, desktop).
Today, Userbase can be used in apps that don’t require end-to-end encryption, for those who like that Userbase can handle authentication, data storage and real-time syncing in a few lines of code.
We also completed a security review by an independent team [2], and wrote up a comprehensive specification of our architecture [3].
Personally I joined in working on Userbase to store end-to-end encrypted data in a performant way for an accounting app. Under the hood, each write to a Userbase database is an append-only transaction to a log stored in DynamoDB (therefore constant time), which is then pushed to connected clients over a Web Socket. Each client then decrypts and applies this transaction to its local state of the database in memory (real-time syncing is provided out of the box). In this process, the server ensures each client receives transactions in a consistent order, 100% of the time. This is unlike some of the (very awesome) decentralized alternatives that exist today (OrbitDB, GunDB, Scuttlebot), which generally rely on CRDTs to stay in sync, and CRDTs can be pushed in any order. For certain applications, the consistent ordering guarantee a central server provides may be extremely useful (such as in an accounting app), on top of the added reliability and performance.
[1] https://news.ycombinator.com/item?id=22145168
[2] https://userbase.com/announcements/#1-security-review
[3] https://github.com/smallbets/userbase/blob/master/docs/userb...
ajconway|5 years ago
jamescampbell|5 years ago
alexobenauer|5 years ago
It's incredibly simple, which is its main draw for me (besides being able to offer e2e encryption to users, which is a huge win for privacy).
nickodell|5 years ago
Hang on, so the process of retrieving the salt gives the remote client information about whether the user exists? Doesn't this mean that an attacker could take a list of possible usernames, and confirm which of them are using your service?
Seems like you could return a salt even when the user doesn't exist, and that would prevent this information disclosure.
j-berman|5 years ago
Additionally, practically defending against user enumeration beyond rate limiting sacrifices a level of security and privacy (for example, by requiring users provide an email to sign up to your service, or through some other means that likely ties the user to an identity and storing this in our database in plaintext), rather than allowing them to use pseudonymous usernames alone.
While we do recognize username enumeration is an issue (because users tend to reuse passwords from other sites, or don’t want to be found out using a site), we concluded that properly defending from user enumeration by default would have too material of a negative impact on user experience for little gain on top of what we already provide in way of protecting user data, and instead focused on defending against potential follow-up attacks by limiting brute force login attempts, and recommending that you tell your users to use a password manager at sign up.
The most significant place defending against enumeration affects is during sign up. When a user’s account already exists, we say the username is already taken, which isn't possible when properly defending against enumeration.
We're planning to allow you to enable email verification in your app if you want to, so users will need an email to successfully create an account. Once that's in place, we'll defend against enumeration more concretely. There are other places in addition to the salt retrieval that would be modified in similar fashion. For example, password reset will need to always successfully return even if a user provided the wrong username, and sharing a database with another user will always successfully return even if the other user doesn't exist (e.g. from a typo).
jamescampbell|5 years ago
jhunter1016|5 years ago
alfongj|5 years ago
Apologies if this is covered somewhere in the docs, but I couldn’t find it.
j-berman|5 years ago
Ultimately we strongly recommend that developers using the end-to-end encryption mode of Userbase recommend their users use a password manager, since losing their password means losing their data (and we try to make this extremely clear to any developers using Userbase via the admin panel and docs). A password manager randomly generating passwords makes this a non-issue.
But alas, we do recognize not everyone will, which is where scrypt comes in to play.
[1](pg. 14): https://www.tarsnap.com/scrypt/scrypt.pdf
chaz6|5 years ago
DVassallo|5 years ago
d33lio|5 years ago