I am new to couchdb so bear with me if this is really easy.
I am trying to prototype a system where there is group of user who can share everything within a database to each other. For example, think of a message board system that once a user is allow into a particular board, they can view/update/delete anything in that message board. Also, a user can join multiple boards.
From what I read so far, the way I am thinking to achieve this is to have multiple database within the couchdb server. Each database represents a board and since board doesn't need to talk to each other, this give a nice separation between boards.
My question is about user authorization. I know that I can create user in couchdb and assign them ACL within one "database", but is there a way in couchdb that it controls user access in a "database" level? ie. which database can a user read/write/update?
the only way I see now is to have another table in a "application" database can control user access, basically a mapping from user to database.
You seem to contradict yourself. You say that you know you can assign a user an ACL within one database, and then you ask if there's a way to control user access in a database.
All authorization is at a database level. Read the Authorization section of the Security docs.
Related
I have a web-application secured with Keycloak. To keep the description of the service short, we have Users and Documents as entities in the service. The users may have access to none or more documents and may edit or read the document.
Currently we have roles such as Admin, EndUser, Developer etc. We then keep a database table outside of Keycloak that maps the documents to users and what user has what access level to what document. All our end-users have the EndUser role in Keycloak. Every single time an EndUser tries to read/edit a Document, we have to make a lookup in the database table for authorization.
We would like to migrate that table to Keycloak. As I understand it I basically have two options:
Create a lot of roles, two for each document with names such as doc_read_[DOCUMENT-ID] and doc_edit_[DOCUMENT-ID] and so on. Then assign the correct role to the correct user. The downside here is that the number of roles will grow A LOT. Also, the number of roles attached to a user will be very large.
Create a group for each document, with the name of the document id. Have different sub-groups for read/write and then add the users in the correct groups. The downside is that the number of groups will be very large. Also, I will rely Authorization on group names, so the list of group names has to be mapped to the token.
I do not want to add a user-attribute with the document-ids to each user. With this approach I can not get an overview of a document and see what users have access to a given Document.
What is the best practice here? Are there any other solutions to solve this issue? This must be a very common setup.
This is just my opinion.
From what I understand both solutions are suboptimal, adding a role per document is unnatural and too finer grain. And as you already mention this would lead to too many roles that probably you will have to add them into the token.
I would personally use Keycloak just for the authentication part and do the authorization part in the backend. I would also try to group the documents in a way that reflect which user roles are allowed to manipulate them.
Alternatively you might try to use Keycloak's Authorization features to handle that use-case, however I have never used it, so there is not much that I can say about this option.
In my opinion what you want to achieve is something that is very tied to your business logic, I wouldn't recomend depending on keycloak to do it. Your token would constantly grow and management would be a nightmare really.
I see no problem in having a service with good cache to lookup permissions, the bulk of the data won't change much over time.
I'm creating a micro services for example one for user management i.e (roles, credentials, rights, menus etc) related and one for bank account-details, now i have a scenario to getting user roles detail and rights detail from db, is it a good practice to repeat columns of database user management db i.e.(roles, rights) in bank-account db as per requirement or duplicate data in bank-account db ?
Or no need to duplicate data in bank-account db and send a separate call to get user data first from user management db ?
please suggest a best possibility
Waqas,
You're in microservices environment. There is a well-known Domain Driven Design (DDD) with one of a key pattern of Bounded Contexts. That means you should try to avoid mixing the contexts and duplicate the user information in bank-account db (it might be inevitable some time, but I suppose not in your case).
Therefore, it's fine that you have to call user management service in order to gain the required information about your users.
I agree with #Stepan Tsybulski. Also, I suggest you reduce the need for a bounded context to depend on the other to the minimum possible. So, duplication of data is the best option here. However, you do not have to have roles and rights in the Bank Account context / DB. I'd put in the Bank Account context only what's necessary in that context: User details (such as names, birthdates, etc.) + user id.
You get the roles and rights from the session. You manage roles in the User Management context only. It's good for security and consistency, plus it's the reason for using Contexts.
There are many ways to approach a problem, but that's how I'm doing it.
This question is regarding authorization, not authentication which i will be managing with passportjs. How do i restrict access for data that's bound to specific users without spreading user_id's all over every table in the database?
Should i create a new database user for each new user of my app and restrict access that way? Or is the "user id in every table" approach actually a good way to go?
I'm working on a project right now where someone else wrote the authorization logic and it works using a kind of authorization path in the code so it can find which user a resource belongs to using some breadcrumb logic.
But I'm really at a loss here and I'm having a hard time finding any information regarding this since almost all articles that I find are about authentication rather than authorization. And I do not mean access to a resource, but rather the filtration of data returned from a resource that the user has access to.
If you want to restrict access of users to certain objects, you either have to store that information with the user or with the object.
The latter is the preferred way because it makes permissions disappear with the object. That's the way PostgreSQL does it – it stores an access control list (ACL) with every object.
So you can either use PostgreSQL to implement privileges (then every application user or at least every group with equal privileges has to have a database user, and you can use permissions on tables and columns and row level security), or you implement it in your application and have some sort of ACL with every row in the database.
I'm new to couchDB and still reading tutorials. My question is if it is the normal way to represent every user of my application as a new database user, as it seems to be explained that way everywhere I look?
Let's say I have an online game with many different players - would I create a new "database user" for every player who registers? Or would I make my own database "players" and create a sign-in logic in the app? Not being used to document-driven DB's it seems strange to me not to distinguish between db-users and users of my application...
You could do it either way. First about couchdb users
Users in couchdb are stored in a special _users database
Database permissions are handled by a special _security document. This is specific to every database.
In security documents you add users that you have already stored in the _users database previously.
So you can certainly create a database per user. Before doing that ask yourself if the data that you store in each database is truly independent. Because you can't run map reduce queries across databases. So if you are planning to do aggregation across data for different users then this approach will not work.
Couchdb can also help you with app level authentication. Since couchdb uses a cookie based authentication:
Store your "business logic users" in the special _users database.
Authenticate it with the _session endpoint.
Extract the cookie header and sent it with your application headers.
All the logic for authentication is implemented for you by couchdb. All you have got to do is manipulate headers. Send the cookie from your application and when authenticating with couchdb send it with couchdb's headers.
If you prefer to write entire session management in your application that is fine too. In this case simply store the users in your database and verify that they exist before authenticating them. Like you would do with another database.
The benefit of using couchdb is that it is secure by default --using pbkdf2 encryption scheme to encrypt passwords.
If you instead want to manage all docs using a single database, but still implementing read/write ACLs, you can check the Chatty Couchapp Tutorial app from Smileupps App Store
It's a pure couchapp, relying on CouchDB only as its backend. The tutorial is still work in progress but the couchapp is fully working and you can download its source code.
It implements role/user based read/write ACLs using a single CouchDB database. This way you don't have to setup N replications where N depends on the number of your users. You only have one database containing all your data, easy to be queried on the fly(with temporary views) and for maintenance operations. Of course you can decide to increase the number of database, depending on type of your data and use cases.
A single couchapp contains all the necessary code for frontend, admin dashboard and server side API implementing business rules
The user, depending on his roles have different access to different sections. i.e. he can access the frontend website, but not the admin dashboard.
You can install the free trial, then download the source code with Smileupps deployment tools, change it, upload it back and check your changes.
Using a strongly typed dataset and its related table Adapters, normally when I want the changes to pass back, just pass it the table and let it do all the work.
What are some easy ways to enforce security roles on the application user as to which fields they can insert/update/delete when the database is using an application ID instead of user level security?
Do I have to go row by row and check each row against what this particular user is allowed to do (by checking the current version of every field against it's proposed version against their role's permissions?
I believe the first level of security would be locking down the columns on the UI a particular user is not supposed to modify, but what about at the data level? Is there a nice way to do this?
Is this easier in linq-to-sql?
First, are you asking about actual security or just control/saftey/fool-proofing (ie stopping users from doing something dumb)?
If you are trying to enforce security try to answer some questions like who is allowed to connect to the database? where is the actual enforcement (eg, application vs connection to the database)?
For example if your application is where enforcement is placed then what if your application is compromised? Can it then connect to the database and do whatever?
For role separation I would suggest different application that are running/assigned different roles. Each role has to authenticate against the database in some way and only have access to necessary data.
In summary, ask who is doing what to whom and what if they were compromised.