Right now raindrop asks the user to enter their name and password for each service they want pulled into Raindrop (Gmail, Twitter, etc…), then stores that information in plain text, either as a file on disk or inside CouchDB as part of a CouchDB document. This is clearly bad. Very bad.
While OpenID+OAuth and similar schemes are good options in many contexts, many services such as IMAP don't support such schemes. Even if most protocols wind up using these schemes, it is likely that at least one raindrop 'protocol' will always need to remember a password for a service. Another consideration is that while OpenID+OAuth etc may avoid us dealing directly with the user's password, we still want to protect the tokens we get back from unauthorized use, same as if we store the name/password directly. As a result, the problem is largely identical for both tokens and passwords; the main difference is simply the consequences of getting it wrong are more severe for the password than for the token.
As if security wasn't hard enough in its own right, the architecture of raindrop and couchdb throws some additional challenges.
- couchdb uses standard http, so any normal http infrastructure (eg, proxies, caches) may potentially sit between the front-end and the couch.
- The raindrop back-end talks to couch via http too and may not be on the same box as the master couchdb. This may be done for load balancing (ie, the couchdb and the back-end get their own virtual machine) or for practical API reasons (eg, the skype protocol only works when logged in via a desktop client, while the IMAP protocol could be run on a box at your ISP)
- couchdb currently doesn't support ssl - currently you need a https supporting proxy server - but you still have clear-text between that proxy server and the couch itself.
This section describes a number of "straw-men" proposals; they all have shortcomings. Please help us thrash this out!
https + only saving in the browser
One possible scenario:
- Make the 'value' of the secret as low as possible - ie, use OpenID+OAuth or similar whenever possible.
- Store the encrypted secret in the browser as part of browser local storage.
- Send the secrets to the raindrop back end using an https connection, the Raindrop back end only stores the tokens in memory, while it is doing the fetch for new messages, sending out messages.
Advantages to this approach:
- This pushes the safe storage of credentials to the browser or whatever client connects to raindrop. This is nice in a way, but may make it hard if the user is using multiple devices and clients.
Problems with this approach:
- Storing the password in memory only while fetching means that the back-end can not synchronize messages automatically - it will only be able to do so when the front-end explicitly requests it and transmits the password.
- Even if we keep the credentials in memory once we have them, if our server processes restart we again lose the credentials, leading to the user wondering why sometimes it can fetch items in the background and sometimes it can't.
- It is also not clear how https requests could be used effectively to a server on a local machine without more involved setup, something that would also avoid any browser complaints to the user about self-signed certificates and the like.
- It will expose weaknesses when an ISP or a user using shared server resources runs raindrop in the cloud - memory might then hold the plain-text version of many users' secrets.
https + only saving in server
- This model would have us choose an implementation of secure local storage which runs at the server.
- Secrets sent from the client to the server use https. A couch external is implemented which takes this secret and saves it to local storage.
- The back-end protocols have this same local-storage implementation exposed (eg as a Python module) and fetch and decrypt the secret in-process, use it, then discard it.
Problems with this approach:
- Shares the same SSL issues as the above approach.
- The passwords etc are still in clear-text in memory for a period, so share those same concerns with the above.
- Too much handwaving - does such a library even exist for the platforms we care about?
How to get involved with Secure Credentials: Post a message or search the archives on the mailing list with "Secure Credentials:" in the Subject.
Right now, any process on the user's local box can get documents and modify things in the CouchDB that Raindrop uses. In other words, there is no checking the authentication or authorization of a request in CouchDB (with the way Raindrop uses it), and right now Raindrop does not have any system or process "in front" of CouchDB. The Raindrop back end is a separate process that runs along-side CouchDB.
CouchDB is growing some OpenID support, but it is not clear yet if it is sufficient for this use case. CouchDB also does not handle https requests.
While running an auth system/server in front of CouchDB might work in the cloud server case, we need something that also works when Raindrop is installed completely locally, on the user's computer.
How to get involved with Secure CouchDB: Post a message or search the archives on the mailing list with "Secure CouchDB:" in the Subject.
There are front end and back end extensions that need work on:
- how to safely distribute them
- determining what sort of access control or sandbox they need to run in, if any.
Jetpack and Google Chrome extensions might have some interesting parts that might inform the discussion. However, unlike those other projects the exact extension points are not so well defined since Raindrop is still in experiment mode.
How to get involved with secure extensions: Post a message or search the archives on the mailing list with "Secure Extensions:" in the Subject.