Handling user account documents

If you store the extra user metadata in SG documents, you’ll need to be careful that (a) clients can’t create or modify those documents, and (b) clients can’t read those documents if they contain any sensitive data. That would be done by your sync function.

You’d then use the SG admin REST API to manage the documents. (CRUD requests made by the admin API have ‘superuser’ access: in the sync function, calls like requireUser always succeed.)

Hi @jens,

I’m proposing creating two types of documents per user:

  1. profile - Using UUID for _id.
  2. _user - using prodile._id for the name.

I believe this way the user can make changes to their profile data, but not corrupt their _user document.

Sure, as long as you set up the sync function to disallow changes to the user document.

@jens,

Is there a way in I can generate a _id value that is deterministic, like using a counter to create something like “u::0001”, with a sync gateway setup?

I suppose you can store your own counter externally and use it in the server-side software that creates those documents. (If you use your own Couchbase Bucket you can use the Increment operation to generate numbers this way.)

Just be aware that a client could (maliciously?) create a document with an ID in this format and cause collisions, unless you explicitly block that in the sync function.

Thanks @jens. This is something I leaning towards because it seems to be advocated as a way to creating documents in couchbase server, http://connect15.couchbase.com/agenda/three-things-need-know-document-data-modeling/.

In following through with you thought, I would create a set of “counter” documents in another bucket and have either app server or client app increment the counters when creating a deterministic _id.

@jens,

Can you explain how the “superuser” access “bypasses” the requireUser or requireRole statements? Maybe provide some examples?

I just posted question that is similar what you mentioned here, using admin rest api on sync gateway

It’s pretty simple. If there’s no user associated with a document update (like if it’s made via the admin port or during a resync operation) then the requireXXX calls turn into no-ops, i.e. they always succeed.

Thanks @Jens,

So say I want the server to create a user profile on behalf of a user, I would use the admin port (ADMIN REST API) which bypasses requireUser. But if I want to give the user authorization to update their own profile, requireUser would do the check. Then any other sync gateway user would get an error response.

Right. So for example you could give the document the docID profile-snej, then have the sync function recognize the "profile-" prefix, split out the remainder as the user ID, and call requireUser to ensure that only the user [or the admin port] can create/modify it.

(Or of course you could put the user ID in some custom property like "user". The nice thing about putting it in the docID is it guarantees uniqueness, since you probably don’t want it to be possible to create multiple profiles for a user. It also makes it possible to look up the profile without a view query.)

Just a side note on your question regarding the deterministic incremental counting : fyi yes, there is a functionality in Couchbase server to implement incremental atomic count (see the counter() method) here:

http://docs.couchbase.com/developer/php-2.0/atomic-operations.html

Additionally, since as far as I understand you don’t need to rely on password management on the sync gateway, I’d suggest you might want to create the user in the sync gateway with a random hashed password as a ‘security best practice’, and then use the session token provided by the sync gateway for its respective auth.

BR / Thiago

Thanks for the tip @thiagoalencar.

Hey @jens,

There seems to be a discrepancy in the documentation for sync gateway session API. In the API reference, it states that the POST params should contain username and password, no mention of ttl. But in pub docs, it calls for username and ttl.

Which one is correct?

You’re right @agillette - that’s a bug in the API reference docs. That’s been fixed in the recent update of the docs - I’ll try to get those pushed live as soon as possible.

Just in case someone else crosses this thread, here you will find a sample implementation using python/Flask (python SDK 2.0), JWT, storing users in a Couchbase bucket with incremental count using N1QL:

github:
https://github.com/tfalencar/cbmobile_auth

explanation:
http://ti.eng.br/couchbase-mobile-with-jwt-tokens/

@jamiltz admin port 4985 not working as like 4984 how can i know or configure my admin port.

Look at the config file. If you don’t see a line configuring the admin interface, it defaults to port 4985.

Jens, i seen config file, but there is no admin interface, so i tried to call www.myipaddress:4985/ on browser, its nothing happen. but when i try to do www.myipaddress:4984/ its showing follow json response.
{
couchdb: “Welcome”,
vendor: {
name: “Couchbase Sync Gateway”,
version: 1
},
version: “Couchbase Sync Gateway/HEAD(nobranch)(86f028c)”
}

4985 is admin port, i don’t know what is the problem.

By default the admin interface only accepts connections from the same host, not over the network. So you’d have to connect from the machine SG is running on, using the url http://localhost:5984.

Just to be clear I think that was meant to be 4985, not 5984.