I am creating a Grails website where users will have access to the resources they create. Till here everything is clear to me. I define ROLE_USER and lock down my controllers and actions using the Config.groovy file.
The issue I am facing is that I have requirement to support group of users such that some resources created by a user can be edited/updated/deleted by other users of the same group. How do I associate a user with a "group" in spring security, what is the design/library I should use here?
What you will need to do is to have your users' roles (the authorizations) come from the database. Once that is the case, you can then easily adjust the roles a user (or set of users) has and create/remove them on the fly. The docs have some pretty good info on how to get the roles to come from the database, so I won't go any more into that here.
Once the dynamic roles are in place, however, you still need to be able to connect roles to the objects that are created. There are essentially two ways you can go about doing this:
Access Control Lists
Custom logic
Depending on the granularity you need and the flexibility you want, one option may be more appealing than another.
Access Control Lists essentially allow you to have a permission mapping between each user and each entity instance. As you can imagine, it's a fair bit of overhead and can perform poorly if you have a large number of entities and users.
Putting together your own logic, on the other hand, is much more flexible because you can set up your own scheme to connect entity instances or entity classes to users and their roles.
I dont think that spring-security provides such functionality out of the box so you will have to do that manually.
For each domain class that you this kind of functionality, store the user name of current logged in user
def authenticateService
def user = authenticateService.principal()
entity.setUser(user?.getUsername())
Then in the update/delete method of the contoller you should check if the role of the current logged in user matches
the role of the user that created the entity. If you have a match you should proceed with the update/delete otherwise throw an exception
/redirect the user to an error page
As role you can use the spring security roles or you can create a property on the user object you have created
Related
I'm creating a jhipster application and I want to let my user access only to the entities that he created, for example in my case I just want to have for each user a special view of the entities product that he created and not for all the products created by other user.
Thank you in advance,
Waiting for your help ...
JHipster does not provide that type of filtering, you'd have to implement it yourself. Out of the box, the only thing you can do is play with the security roles, both in the front-end and the back-end (as pointed out by #gaƫl-marziou).
In the front, using authorities in the state declaration (entity.js file). In the back, using #Secured in the controllers (EntityResource.java).
In order to the type of filtering you need, you have to create new attributes in your entities to store the user that he/she created, and then create new methods in your repository to do proper queries.
What is the best way of dynamic authorizing users with their roles. Indeed I have some roles that changes overtimes and currently I have this code for some of my actions or contorllers:
[Authorize(Roles = "Admin,MainFedration,FederationUser")]
public string ConfirmAccident(int? id)
{ .... }
Then if a role add or change it's permission i should search and change most of actions and roles to config new permission.
What is the best way to remove this redundant work?
The only other way would be to configure the permissions each role has in a database and then subclass AuthorizeAttribute and overload the logic for how it determines which roles are allowed by utilizing the database-stored permissions.
However, it should be noted, that this is a problem mostly because you're using roles improperly. I see this all over, even in official Microsoft documentation, which is part of the problem. Something like "Admin" is a group; roles are different and should be things like "CanEdit". A group or a user can be assigned roles, so any user in the "Admin" group, would have the role "CanEdit". Then, you don't have to change the roles config on the action because the ability to edit is the ability to edit, no matter which users or groups have it.
Maybe you should take a look at how Access Control is organized: https://nsecurity.codeplex.com/. Here's a simple solution which outlines the principles of Access Control Entries, Access Control Lists, and how access to items, subject to security restrictions is set up. This way of (dis-)allowing users' access to certain items is much like the way it is organized in, say, Windows file system.
The idea is really simple: instead of giving user permissions (not) to do this or that, the items are guarded and access is granted/denied once a simple condition is satisfied. In other words, security is not geared towards users, but towards "securables". Or, keys are used to lock/unlock doors, but not to prevent users from moving around.
I'm building an app that users have to register before they can view the content, I am using Parse for my database needs.
What I need is have a class of Users (Parse.User) for regular users and a class of Users (Parse.User) for admins. The regular users would only be able to access the app, the admins would only be able to access an admin website where they will add the content (products) that will show up in the app.
Is it possible to create 2 different classes of Users with Parse? Or should I create the admin user class manually (not using Parse.User)?
Thanks for the help! I'm pretty new at this databases and user thing haha
What you really want is to create a Role for Administrators. You can assign ACL permissions to this Role and it will be respected throughout Parse. As you add/remove Users from this Role they automatically have the permissions of their current Role(s).
You can read more about Roles in the documentation, there's a whole chapter about it.
I'm fairly certain that you can't create 2 different User classes. (Though I may be wrong.)
But regardless, the easiest way to do this would probably be to keep all the users in the same class and just add an admin boolean key to indicate whether or not the user is an administrator; then log the user in (to access the current user's keys) but only proceed with the actions following a successful app login if the admin value is set to false and, likewise, only proceed with the actions following a successful website login if the admin value is set to true. If the admin value indicates that the user shouldn't be logged in on that platform, don't proceed with the login and instead log the user out.
In my App, a user can take on more than one role. My solution to this is to have a User class and then a pointer for each type of user (could be a regular object pointer, but I use something similar). So there would be an "adminLink" pointing to the Admin role-specific object and a userLink pointing to the user role-specific object. The pointer designates the object containing the attributes relevant to that role (user or admin). Attributes common to all roles are stored in the User object.
"Roles" (capital R) are needed to control access to objects. So for each User, you may need to create a user Role and an Admin Role if the person performs both roles (small r). You have to have a reference for each Role. These can be stored either with the User object in separate attributes or in the role-specific user objects.
-Bob
New at ASP.NET MVC. I am looking for some UI design ideas not entirely specific to MVC. There is probably not an exact answer but here is what I have started.
There would need to be a page with 3 tabs on it.
Permissions | Groups | Users
1) Permissions View would allow you to do CRUD operations on Permissions in a Grid
Delete on a specific permission is only allowed when the permission is not being used in any Group.
2) On Groups View, CRUD operations on Groups are allowed in grid.
Also, a Permissions link is provided that will allow to do mapping (Add/Remove) Permissions for a Group
Again, a DELETE operation on a Group is only allowed when the Group is not being used by any User.
3) On Users View, all the existing Users in the system will be presented. The grid show allow for searching a user by username, first name or last name.
Groups link should be provided for each user that when clicked allows to do mapping (Add/Remove) Groups for a User.
Below this mapping in the same view, a separate section of Permission Overrides should be provided so that a specific permission can be added with IsGranted (true/false).
Description of the database design:
1) Groups will be assigned Permissions. Based on the group that the user belongs to, User will get the Permissions.
2) UserPermissionOverrides will handle the scenario where
- a User needs to be granted certain permissions (regardless of the role they are in) or
- if certain permissions need to be revoked from a user, even if they belong to a certain group.
This will allow us good flexibility to handle the special scenarios of adding or removing specific permissions.
So, when the user logs in - 1) above will be used to retrieve the group permissions for a user and then 2) will be executed to retrieve the overrides (granted/revoked). Combining 1) and 2) will give us the final permissions for the user which will then get stored in the forms authentication cookie to prevent further database hits
Your model and functionality all make sense to me. However, I think you need to revisit the UX principles you are employing for the interface.
Write a few user stories i.e. what a user of the security system intends to do and what goal they need to fulfill for that visit.
You need not always tightly couple your UI to your model i.e. just because you have structured your model in a certain way, those entities needn't be presented as principle objects for CRUD operations to a user. It's probably very unlikely that a user of the system will come in, add a permission and leave.
Pertaining to the above, personally I would approach your user permission UI as a wizard rather than a set of tabs:
Step 1: Pick a user or add a user.
Step 2: Which roles do they need (offer the opportunity to add a role).
Step 3: In which groups do they belong (offer them to add groups here if necessary).
... or similar.
Basically, your aim should be to get your user in and out of the system as quickly as possible. I think the act of creating user stories and wizards you glean from them would be the method I would employ in the UX design of your system.
Good luck!
I'm contemplating a multi tenant application - shared database, shared schema. A tenant identifier (tenant key) associates every row with the right tenant.
What i'm not sure about is how to go about loading the tenant_id into some sort of global scope. How should this happen? I assume that I would parse the domain and then look up the tenant_id based on the domain.
My questions:
Where would the lookup happen in a rails application? In an initializer? Is there a better point to do this?
Once I have determined the tenant_id, what is the best way to persist it - a simple session_id?
I use a before filter for the controllers for this function.
You can also sub-class the controller class to DRY out duplicate code in the controllers.
Be careful to remember that access to a given tenant's information needs to be authenticated on a per-user basis. You need to decide if a given user will have access to more than one tenant. Eg should user "joe" have access to tenants 1 and 2? Or should Joe need a per-tenant login?
The login's authorization should control access to the tenant info. Don't rely on the domain name to grant authorization.
Re: where to persist the tenant_id? Store in the session. If access to the session is expensive (stored in DBMS), then make an in-memory copy as an instance variable during the controller startup. Google for how user_ids are often stored.
You also should determine the user experience for if/when a user wants to access a different tenant.
Added To see which welcome screen to load before the user has logged in, looking at the subdomain name is a good choice. To see which subdomain the incoming request used, parse request.fullpath() Docs. Do this in a controller filter.
Since the authorization comes from the user_id, remember to test the case where joe logs in at tenant1.app.com but only has access to tenant2.app.com
Bonus answer Looking for a templating system that will enable your customers to have full control over their tenancy's user interface? Check out Liquid templates. I was very successful in using them to enable my customers to have full control over their look and feel in a safe way.
Re additional questions in comment
See superuser for configuring the web server. The config is web server-specific.
If you want the welcome screen to not be generic, then you must know from the request url how to customize it. Tenant-specific subdomain is the nicest. If no subdomain, then show the generic welcome--when the person logs in you can determine the tenant and how to customize.
Re helper--if you mean a view helper, then I would not recommend it as the primary place where the tenant is determined. Make the #user and #tenant be light-weight models that you look up once and then retrieve from the session during additional requests for the same session. The models will be used by the controllers and, perhaps, passed to the models. The View layer will also be able to see them and use them as necessary.
If the UI may look/will look completely different for the different tenants, then add a "tenant-display" layer in addition to the view. Eg have the view gather the instance variables, find the right Liquid template, then express the view via the template.
You don't want the view to be computing "if tenant_a then x else y"