Relationships and References in Mongo DB - mongodb

I am currently working on a project in which there are many threads that users can create. User's have different permissions for the threads that can be specified by users with admin permission. User's need to be added to the thread before they have access to it.
When a user is added to the thread, they are given either read, write or admin permission. Users can also be part of groups. These groups can then be added to a thread in which case, all users in the group will be added along with the permission that is specified for the group.
thread: {id: xxxxx, users:[{id:user01, permission: write, discovery: non}, {id:user02, permission: read, discovery: GroupA}]}
So a user can be added with an individual permission or they can be added with permission given to the group they are a part of. Discovery would specify whether the user was added individually or as a group.
I am wondering if this would be the best method of setting up Mongo for this sort of permission system and also how I would actually define this schema using Mongoose? I think that it would be fastest to have all these aspects embedded into each thread.

Related

REST API: Authorize access based on given permissions rather than pre-determined roles

You all are familiar with the ability to share a Google Doc with certain people, and provide those people with the ability to view, or edit.
I'm trying to understand how such an architecture would be organized in a REST Api.
For instance, for my document I want to grant read access to:
myself
some#email.com
users who belong to domain.com (everybody who belong to my network)
I'd like to give write access to:
myself
another#email.com
In addition, users with the role of admin also have write access regardless of the permission I define, and users with the role moderator have read access regardless of the permission I define.
What would be the ideal (or best practice) architecture for such a thing? Where would I deligate permissions? On the document itself? Would I have another model handling permissions? How would I create the complex rule-based system where access is granted based on a specific email, a broader domain affiliation, and an even broader site-wide roles.
I can imagine a situation where each document has field for different permissions. For instance:
owner: my id
admin: all the site's admins
moderator: all the site's moderators
viewers: a list of emails / domains
editors: a list of emails / domains
But, is this scalable?
I'd love to get some advice.
Thanks!

Keycloak -> How to fetch permissions attached to a single role or group

Scenerio :
Use Groups for multi tenancy (One user working for different organizations) -
Create one group for each org like group_org1, group_org2 etc.
Provide permissions to above groups using group policy (using confidential client authorization tab). Ex :- group_org1 has permission on resource1 and group_org2 has permission on resource2.
Assign above groups to a user , hence user will have 2 groups and, permission on resource1 & resource1.
Now groups fetched for this user will be used as organizations in application.
When selected org1 then application will work according to the permissions attached to group org1 i.e. permission only on resource1.
Question :
As of now if I try to fetch authorization permissions for a user then keycloak will give me combined permissions attached to both the groups i.e. on resource1 and resource2 . I need to fetch permissions attached to single group using keycloak rest-api. (after fetching this specific permissions I can authorize user in the application for given resource)
Hope I made my question a bit clear.

Keycloak redirect fails when number of roles are in the hundreds

I have 2 users, one with less than 30 roles and one with 400 roles. When I login with the 30 role user, I can reach the redirect URL without issues. But when I log in with the 400 role user, the request to the redirect URL doesn't complete. If I reduce the number of roles in the 400 role user then it will work. So, is there a way to disable passing roles in the java access token or increase some limit somewhere that's causing the failure?
I would suggest to focus rather on roles reduction/optimization than forcing the transmission (raising limits) over the maximum number of roles inside tokens (or anywhere else).
Some interesting questions (among others) to start with:
Which protected resources am I going to serve?
What am I trying to protect? and what are the associated risks? (build a Threat Model)
How do resources are served by each application? and how are they distributed among my applications?
What kind of resources are they? How can I group them? Which sets are identifiable? or what are the relationships between them? What actions are possible against all sets of resources?
Who are the users of each application? How will they interact with my resources? Which flows are sensitive?
What roles can I define for all my resources?
Which role can apply to each application, resource type or set?
What kind of user groups can I create?
Do I need additional attributes or claims for each set of roles or users/groups?
I firmly believe that if you answer all these questions you will end up having a bunch of roles instead of hundreds. Think security by design and follow principle of least privilege.
Focus on your use case
Now as far as I understand, your blocking point is that you are assuming that each resource is unique, sensitive and requires its own permissions, and consequently a role definition. While it may be true in some cases, in most other cases it does not mean that you have to use the token roles/scopes/claims to secure your assets deep at the resource-level. I'll try to illustrate this sentence by an example.
RBAC and authorizations example for your use case
Let's assume that:
you have millions of sensitive resources to serve
each registered user of your application has access to a (different) set of these resources.
your resources are splitted into, say, 3 categories (e-books, videos, musics).
each resource can be downloaded, uploaded, deleted.
your application will meet unregistered users, registered users, contributors and administrators
registered users will always have read access to resources (not a single action will ever allow a modification)
contributors are particular registered users who can perform special actions including modification ('upload', 'edit')
contributors and administrators may have access to various administrative parts of the application
your application will evolve by serving additional categories of resources in the future and new actions will be available to users later (such as 'flag', 'edit' or 'share link').
Then first things first:
organize your resources accordingly by serving them behind categorized paths such as: .../myapp/res/ebooks, .../myapp/res/videos, .../myapp/res/musics
identify your resources via UUID such that a resource may look like: .../myapp/res/ebooks/duz7327abdhgsd95a
Now imagine that your business risks or at least the greatest risks you wish to avoid are:
unregistered users having gaining access or rights for any part of the application or resource
uncontrolled registration process (robots, spam, no mail verification, fake users, ...)
registered users gaining illegal privileges (unauthorized actions, access to other categories, illegal administrative rights)
discovery of available resources by any mean
You will note that I voluntarily didn't listed:
registered user having illegal access to certain resources. For example: maliciously pointed/provided by an existing user.
This is because it is not a high risk as you may hold contact information about registered users as well as log activity and actions, quota or requests throttling, and you may be able to ban them or start legal action against them. Your registration process is also assumed robust and secure. Nonetheless if its considered a critical risk you can address this with extra mechanisms (cf. suggestions at the end). But never will it result in adding extra roles, such as one per resource, as it does not fit in any security model.
That being said, finally, here are the roles and authorizations scheme you may come with:
SCOPE / AUDIENCE
MY_APP
ROLES
USER
CONTRIBUTOR
ADMINISTRATOR
CLAIMS / ATTRIBUTES
CATEGORIES
ACTIONS
--> POSSIBLE USER GROUPS
USERS
Roles: USER
Claims: CATEGORIES(variable), ACTIONS('download')
CONTRIBUTORS
Roles: USER, CONTRIBUTOR
Claims: CATERGORIES(variable), ACTIONS('download', 'upload', 'edit')
ADMINISTRATORS
Roles: USER, CONTRIBUTOR, ADMINISTRATOR
Claims: CATEGORIES(*), ACTIONS(*)
Following this model, assigning the correct group to each registered user will provide high-grade security by mitigating/controlling the main risks. As claims/attributes are defined in the token(s) (managed and signed by Keycloak) then you can trust this information in your application and serve your resources accordingly and safely. There is also no risk of illegal access or discovery of resources as you are using UUIDs, only registered users having had access once to a resource will know it and registration with appropriate category access will be needed for another user to access it (to only be able to read it basically). Of course you may store in a database the list of resources to which each user has access to, raising the overall security to a very high level.
However, if the latest is not enough you may also implement rolling UUIDs or temporary links for your resources when served to users. To go farther you may also define groups and masks for your categories, resources and actions.
In fine, in this example I made use exclusively of token claims to define roles (common claim), categories and actions (custom claims). In terms of security the authentication and identity will be the first-line security followed by roles then categories, actions and stored list of resources per user (db).
Other alternatives are obviously possible, its just an example. Still, I hope it helps!
To fix this problem you should start from defining client scope mappings for each of you applications (e.g. oidc clients). Main idea of this facility is that even if your user is super duper admin with all existing roles, all of his roles actually don't required for any particular application. For example client foo which defines following roles:
foo_user
foo_viewer
to perform its security logic need to know only whether currently logged user has foo_user or foo_viewer, but it doesn't care about has this user roles bar_user or bar_admin from application bar. So our goal is to make Keycloak return for any client access token with only valuable set of roles for this client. And roles scope mappings is you friend here. You can set for client foo scope like:
foo.foo_user
foo.foo_viewer
bar.bar_admin
and now even if logged user has role "bar.bar_admin" this will not go to access_token since client foo doesn't take this role into account. After applying some scope settings you can test them at 'Clients -> $CLIENT_OIDC_ID -> Client scopes tab -> Evaluate sub tab.
As for you case with 400 roles, i'm quite confident that none of your application requires all of 400 roles, so precise scope configuration for you apllications can drammatically reduce access token size.
But if i'm mistaken and you really have an application that rely on large amount of roles you should look into you runtime settings.
For example if you run keycloak behind reverse proxy like nginx large tokens may not fit in default HTTP parameters buffer size (afaik about 2-4kb) so you have to increase it via appropriate nginx configuration option. Another example is tomcat which has about 16kb as default HTTP header buffer, so if you send request with very large access token in Authorization header Tomcat may not handle this request properly.

Get list of users which have a specific or set of permissions

Using Shiro with JDBCRealm
My use case requires a user to submit a form to next user. The next user can only be someone with specific permission. This is to be known in order to show only valid Next user list for selection.
How can I get list of all the users that have a specific permission?
If not, Is there a workaround of getting the User permission strings from database and then at least reuse Shiro's logic to check if the user has specific permission?
Shiro is related to only security, authority, etc of current user not to the whole user base. You can use your standard sql queries to retrieve users with same permissions of the current logged in subject.
Why not use simple SQL query that matches current user permissions to other users permission and give a list. This way you will save memory and resource by not computing permissions logic in java again.

Permission control using apache shiro

I am new in apache shiro, and I read almost 60% of tutorials in apache shiro page.
It is a wonderful framework, however I wonder if it can meet my requirements.
I am interested in the permission-based authentication.
For example, to make sure if the user have the permission of delete resources, we can use this:
currentUser.isPermitted( "resource:delete" );
However in our application, even a user have the permission of delete resources, he can only delete some specified resources, not all of them.
For example(just an exmaple), the resource have an filed named createdby to record the one who create this resource.
Now user can only delete the resources created by himself if he have the resouce:delete permission.
In fact, the resources which can be deleted by the user(who have authenticated and have delete permission) will be calculated by more constraints.
Now how to make shiro work in this suitation?
You can do this in Shiro but you will have to write some code. Either create a subclass of Authorizer and inject it into the security manager or create a subclass of one of the realm classes such as JdbcRealm. Then override the isPermitted method. This will need to have access to your permissions model, for example the database table or a document in a NoSQL database.
Your call to isPermitted will need to specify the resource you are deleting so you can look it up in your overridden method.
If you override the isPermitted method in the AuthorizingRealm subclass you will have access to the logged in user's principals and the user's Roles: this gives you quite a bit of flexibility because you can have says: user (principal) Fred with roles: Manager, Administrator. Your permissions model can then decide if Fred, a Manager or and Administrator can perform the task on the specified resource.
Hope that gives you some ideas.
From the extent, I have explored Shiro, I don't think it gives that level of flexibility to have a customized check. It basically functions based on roles and permission defined in the config file.
For this functionality I would suggest that you display only those records the user is allowed to delete, by have this check at query fetch level. (or) add a condition at the UI level not display the delete button if logged in user is same as created by. This is just a suggestion.