You may find this library useful if you want to go with solution 2: https://github.com/maxogden/ezcrypto-js
On Fri, Mar 25, 2011 at 8:07 PM, Nebu Pookins <[email protected]> wrote: > > Thanks Patrick, > > my follow-up question is: What if Sever 2 can't "trust" Server 1? For > example, Server 1 is actually an "offline" version of the blogging > platform downloaded onto Alice's laptop so that she may continue > blogging while offline, and then, when she comes online, her work is > synced back with the cloud. > > If Server 1 claims both Alice's and Bob's posts have been modified, it > seems like Server 2 would be unable to distinguish between these two > scenarios: > > 1) Alice and Bob are friends, and Alice lent her laptop to Bob so that > he could do some offline blogging too. > 2) Alice is maliciously forging blog posts under Bob's name. (She > might not even actually be running the CouchApp locally, and is merely > sending carefully crafted HTTP requests via curl to simulate > replication). > > The two partial solutions that immediately come to mind are: > > 1) When a user downloads their own instance of the CouchApp, it's > "tied" to that user. Bob cannot use Alice's copy of the CouchApp to > blog; but if Alice had the foresight to download a copy both under her > account and under Bob's account, then they can still share a laptop > for offline access, although in different copies of the app. > 2) Use public key cryptography and signatures, such that every change > is signed, and every server can verify the signature of every > modification to see if it really came from who it should be coming > from. > > Solution (1) is unpleasant for the end user experience, but otherwise > seems straightforward to implement. > Solution (2) seems much more difficult to implement (JavaScript's > treating of all numerics as floating points, whereas Cryptography > typically works entirely with very big (e.g. 128bit, 256 bit, 4096 > bit, etc.) integers makes the two look like a mismatch without first > writing a Bigint library), and while in theory seems to be much more > pleasant for end users, in practice I believe the user would not only > need to provide a password, but also their private key renders the > user experience unpleasant again. > > I'll probably end up going with solution (2) because the proposed app > we're building will have to deal with banking and financial data, so > we're going to have to have some cryptography in there anyway, but I'm > just making sure I'm not missing anything (such as CouchDB already > having some sort of encryption library built in). > > Thanks again, Patrick, for clearing things up for me. > > - Nebu > > On Thu, Mar 24, 2011 at 7:01 PM, Patrick Barnes <[email protected]> wrote: > > You're quite right, it would fail on replication. (And if you identified > > that issue solely from a hypothetical standpoint, well done) > > > > The solution could be to give your replication user as 'replication' role, > > and have the validator function look something like: > > > > function(newDoc, oldDoc, userCtx) { > > function to_object(arr) { obj = {}; for(var k in arr) obj[arr[k]] = > > true; return obj; } > > if (newDoc.author) { > > if(newDoc.author != userCtx.name and !('replication' in > > to_object(userCtx.roles))) { > > throw("forbidden": "You may only update documents with author " + > > userCtx.name}); > > } > > } > > > > -Patrick > > > > On 25/03/2011 4:46 AM, Nebu Pookins wrote: > >> > >> Hi, > >> > >> I'm reading "CouchDB The Definitive guide", and in the chapter on > >> "Security" (http://guide.couchdb.org/editions/1/en/security.html), > >> they give an example of how to limit write-access to certain documents > >> based on its owner. The example validator function they give is: > >> > >> function(newDoc, oldDoc, userCtx) { > >> if (newDoc.author) { > >> if(newDoc.author != userCtx.name) { > >> throw("forbidden": "You may only update documents with author " + > >> userCtx.name}); > >> } > >> } > >> } > >> > >> If I understand correctly, userCtx is based on the HTTP request of the > >> POST/PUT/DELETE request which is trying to modify some document: If > >> I'm logged into couch, either via HTTP basic authentication, or > >> cookies, or something along those lines, then my username will show up > >> in the userCtx, and we simply do a string comparison to see if I'm the > >> "author" of a given doc, and if so, then the business rule is that I > >> should be allowed to change the doc. > >> > >> Elsewhere in the documentation, it mentions that validator functions > >> are run not only when POST/PUT/DELETE requests are made, but also when > >> replication occurs. What I'm confused about is what the value of > >> userCtx would be during replication. To give a more concrete example: > >> > >> Let's say we have 2 couchDB servers running, called Server 1 and > >> Server 2, and they've replicated with each other so that they both > >> contain identical data: a set of blog posts. > >> > >> A user "Alice" logs onto server 1, and edits one of her blog posts. > >> The validator function runs, and given that it's Alice that's logged > >> on, the validator function checks that the blog post's "author" field > >> is Alice, and assuming it is, it allows the update to occur. > >> A user "Bob" also logs onto the same server, edits one of his blog > >> posts, and again the validator allows it. > >> Then both users log off, and go do something else (e.g. watch a movie, > >> read a book, etc.) > >> > >> Now replication occurs: Server 2 will ask server 1 for a list of > >> changes, and server 1 will report that two blog posts have been > >> changed. > >> > >> Given that neither Alice nor Bob are connecting to server 2, it would > >> seem that the userCtx variable would not contain either of their > >> names, and thus the validation would reject the change, and > >> replication would fail. > >> > >> i figure I must be misunderstanding something about how either > >> validation or replication works, but I can't seem to figure out what > >> from the documentation. Can someone help clarify this for me? > >> > >> Thanks, > >> Nebu > >> > >
