Authentication strategies Users, Roles and Channels


#1

Hi again,

Thank you for your help so far. I have found it really useful.

I have been investigating how we restrict access to couchbase and are seeking any guidance or alternatives to the approaches we are considering.

At the moment we have the following…

  • A channel with multiple documents. There will be admins in the channel who can add other users, and then there will be people who can read, write and delete documents from the channel.
  • A user who creates a channel will be the channel admin, but it is possible that in the future they leave the channel altogether and one/many others will continue to admin the channel.

My understanding is as follows.

  • Roles restrict access to channels.
  • Channel filtering restricts who can read documents, but not Create, Update or Delete.

Strategy 1:

  1. Create a document in each channel that contains the various permissions (Create, Update, Delete, Admin) and which users they are granted to.
  2. In the sync function retrieve this document and check a user has the permissions to do what they need to do.
  3. To add or remove permissions modify this document.

Strategy 2:

  1. Create roles for the different permissions channelname-admin, channelname-read, channelname-write, channelname-delete etc.

  2. Grant these roles to a user.

  3. In the sync_function do something similar to the following

    function(doc){
    var channel = doc.channel();
    if(writeOperation){
    requireRole(channel + “-write”);
    else if(deleteOperation){
    requireRole(channel + “-delete”);
    …etc

To be honest I am not particularly comfortable with either of these strategies. The first results in a call to the db for the permissions doc in every sync. It does make it easy to revoke permissions from a user though. The second strategy results in a ridiculously large number of roles and it is not clear how I would go about removing the roles from a user. At a glance it looks as though I would need to iterate through every user in the db, check for a role and remove it. There does not appear to be a way to grab all users with a given role?

Finally, I have considered changing the relationship between docs and channels to be one to one. Having a single document that has documents nested within it. However it feels wrong and there is a limit on document size that could be reached.

I’m really interested in hearing how others have approached this problem or any standard patterns for access and authentication through the sync gateway that might work for this scenario.

Thanks

Simon


#2

There are a few points that you don’t have quite right - clearing those up might help you get to a design that works for your use case.

  1. Roles and users can both be granted access to channels. Users can be granted roles, and inherit any channel access for those roles.
  2. Channel access determines a user’s read security. Write security can also be based on channels (using requireAccess), but can also be based on user/role (requireUser and requireRole), or document content (using throw).

You can’t read another document during sync function execution.

Instead, one approach you might consider combines aspects of both of your suggested options:

  1. For each channel, define channels for read/write/delete/admin. No documents would be assigned to those channels - these channels would be strictly to manage write security.
  2. Use an admin document to manage access to those channels, using the access() call in the sync function.
  3. Use requireAccess() to validate document writes, based on those channels.

#3

Thanks Adam,

That has made things much clearer for me.

Simon


#4

This tutorial might help as well.
It references some paragraphs from Adam’s answer. It’s not exactly the use case you described but will help understand roles in general.

James


#5

@jamiltz The link is dead, would be nice if anyone can update the link.

I am trying to do the same as @sgmccli, check rather User have specified role and allow read only access or both read and write access. But I have no idea how to check if the operation call to sync function is write operation or not. I hope I can get some hint here.

Thanks


#6

@kchan4 Oops, this tutorial moved to the mini-hacks repo https://github.com/couchbaselabs/mini-hacks/tree/master/channels-users-roles

Let us know if this helps in your scenario.

James


#7

Thanks @jamiltz !
I just realized I have a misunderstanding on the usage of sync_function.
sync_function is only being called when adding/modifying document, is not being called on read.
So I can simply add requireRole() in sync_function to add write permission restriction on all document. :smile: