I am developing a spring boot application with spring-data-rest being one of the core dependencies. As such, in order to secure the auto generated and manual endpoints I have been using a role based approach and a custom PermissionEvaluator to handle object specific auth checks. This works but is too cumbersome and fails when I need a filtered and paginated response. So, I am planning to implement ACL. Now, I have a rather complicated flow of authorisation for an entity.
The users are mapped to a profile entity(MANY TO MANY). The target entity is also mapped to a separate profile entity(MANY TO MANY) and these 2 profile entities are mapped to each other(MANY TO MANY). To check if a particular user has permission over a target entity object, I need to go through the relationships in my application logic, in my PermissionEvaluator.
Now, if I decide to implement this in ACL only, I am confused as to how to best to do this. The preliminary idea that I had is to create the object list directly in the ACL tables for each user(principle). This would mean that I would need to update the ACL tables everytime with new objects if a permission is changed. Is this a correct approach? Is there a better way to do this? Is it even ok to modify the ACL tables frequently?
Summary: If the logic to check if a user has access over an object is complicated and requires data from other tables, how do I handle it efficiently using ACL?
I'm working on an ACL extension for Spring Data JPA/Rest which handles all of your problems - and many more. It take some time to learn how does it work, but it still needs much less time than creating all of these features for yourself.
You can set up the access rules using annotations in the entity classes - and that's all. it will affect the auto-generated and manual endpoints and even the Data JPA repository-methods.
Spring Data JPA ACL
Related
I have multiple closely related problems in Spring Security. I am developing using Spring Boot and am using Spring Data REST for creating REST endpoints directly from my repositories.
I have multiple entities and the requirement is to have all these entities as REST endpoints. I am letting spring-data-rest handle the creation of these endpoints and I am securing these endpoints by adding #PreAuthorize and #PostAuthorize to the entity repository methods as and where required. This works great when I am calling an endpoint like /entity/id.
But I am facing issues from here. Let's say I have 2 entities, Entity1 and Entity2 and they have a One to One relationship. Spring data rest allows me to fetch the related Entity2 data from Entity1 like /entity1/id/entity2. But I have different access rights over Entity1 and Entity2 and calling the above endpoint only checks the access rights as set up in the repository for Entity1 only. So, if a user has access to Entity1 table and no access to Entity2 table, he can still see some Entity2 data via the foreign key relationship of Entity1. Is this a correct design?
Moreover we have some custom API endpoints wherein we have to aggregate data from multiple entity repositories. Also, these endpoints themselves have to secured. So, I am using a #PreAuthorize over an endpoint method. This works as expected and the endpoint method is called only when the expression is valid. But, when a repository method is called (via a service class of course), the #PreAuthorize over that repository method is also evaluated. I would like to have the check done with at the beginning. Is it possible to do so?
Any suggestions to improving the design is also welcome.
There is no simple solution without massively modifying/overriding lots of default Spring DataRest features. I'm working such a package for years now and it's working quite well for me.
Although switching to this package might be a bit overkill for you, it could worth the trouble in the long run because it also a fixes a lot of problem you will meet only months later.
you can set up permisison rules via annotation directly in the domain objects.
it checks the permisisons in the DB side, so the traffic between the API and DB is heavily decreased (Only those objects are fetched form the DB which the current user has permission to)
you can set READ/UPDATE/DELETE/CREATE permissions separately for roles and/or certain users
you can use pagination on permission filtered collection
you can use pagination on property-collections too
(+ some extra features like flexible search on multiple properties)
here is the package (It's an extension of Spring Data JPA / Data Rest)
Spring Security has this basic idea of a Principal and GrantedAuthority. I've implemented Spring Security and read this stackoverflow and understand at a basic level that a "ROLE" is nothing more than a GrantedAuthority prefixed with "ROLE_".
What I don't understand is why have this convention in the first place? Why have #PreAuthorize("hasRole('XYZ')") be equivilant to #PreAuthorize("hasAuthority('ROLE_XYZ')")?
What's so special about segregating Granted Authorities like this? What's the purpose?
Additionally, what is the best convention for applying these "ROLES" to specific instances of a Domain Model. Take for example a system that keeps track of projects and you want to explicitly give users access to view and edit certain projects. I could create ROLE_EDIT_PROJECT and ROLE_VIEW_PROJECT but that's application-wide. Where would you make the relationship of a ROLE to a specific project? A join table? Would you even involve Spring Security into this or build this type of security from scratch within your application?
I unfortunately don't know why this convention is used, probably just legacy code I would guess.
For the second part of your question, I would suggest using "hasPermission(project, 'view')" and define your own PermissionEvaluator.
more information can be found here
Spring Security ACL looks very powerful, and easy to implement when you can stick to their database implementation. However it appears to become much more complicated when you have to implement your own Acl and AclService (see for example this (old) very basic tutorial of only ~26 pages) and it seems difficult to find references and examples for it (that tutorial was from 2008).
In our application for example, users have roles and belong to departments. Most of the time, they are allowed to perform some operations on objects that belong to their department based on their roles. In all cases, department + role is sufficient to decide whether a user should be granted a specific operation on a specific object.
Users, roles and departments are managed by an external application from which we retrieve them when the user connects (we are using REST services but it could as well be an LDAP server).
We would like to rely on #PreAuthorize('hasPermission(…)') for implementing domain object security. 2 solutions are thus in sight:
Implement a custom PermissionEvaluator that does the whole checks; or
Implement ACL with a custom AclService that builds the object structure necessary for ACL's to work properly.
It seems that implementing the whole AclService would be more difficult and more complex than implementing a PermissionEvaluator, but ACL's seem to be more standard.
Based on which criteria should you implement one or the other?
The PermissionEvaluator is responsible for expression evaluation to determine whether a user has a permission for a given domain object. On the other hand the AclService provides an interface for retrieval of Acl instances. In the spirit of Separation of concerns each component addresses a separate concern.
If any PermissionEvaluator implementation needs to perform evaluation based on Acl instances, it should delegate to AclService to retrieve them. Actually AclPermissionEvaluator does exactly that.
I would suggest you to go this way. Separate evaluation from ACL retrieval. If the concept of Spring AclService and Acl is too complicated or complex for your use case, you can introduce your own service to retrieve custom ACL. Then implement PermissionEvaluator that will delegate to your ACL service.
Actually, I had to do something similar because I needed to store ACLs in NoSQL database and what Spring provides did not work for me.
I would say that it is all about the effort needed to adjust Spring ACL to meet your requirements and the effort to implement a custom solution. If your requirements can be satisfied with the default Spring ACL implementation, go for it. It will definitely save you time to implement your custom solution. However, if it is not possible to adapt Spring ACL to your requirements or it would be too difficult, then it can be easier to implement your custom solution.
I'm coming from the PHP world. The framework I used most is Symfony which is heavily based on ideas from Spring. One if its bundles called JMSSecurityExtraBundle supports a role ROLE_IDDQD that you can activate via configuration. Authenticating with that role would effectively bypass all the security checks — be those Web security constraints or constraints directly on methods of classes in the domain layer.
Since security related tests needed a user with a particular role to be authenticated, I would authenticate a user programmatically creating an authentication object and passing it to the security context. That way I could test security constraints directly on the domain code without involing any UI.
Since a lot of domain methods would be secured, it would prevent me from setting up fixtures for some of the tests because the currently authenticated user wouldn't have enough permissions to do that. This is where I started using ROLE_IDDQD — I created a method that would take a function that could do anything in the domain layer bypassing any security constraints:
$user = $this->iddqd(function () {
return $this->userManager->save($this->aUser());
});
That method would remember the current authentication, reauthenticate with ROLE_IDDQD, execute the function passed in and then restore the remembered authentication.
I'm migrating the app to Spring and looking for a way to do the same with Spring. I couldn't find any mention of ROLE_IDDQD, so I guess that part wasn't based on Spring Security. Are there any other means to replicate this functionality?
Spring security has a concept of Anonymous user with automatically assigned role "ROLE_ANONYMOUS". You can look for more information here
I solved the problem a long time ago. Here's how I did it.
In my architectures, I usually have a repository layer that abstracts away database access and a manager layer above the repository layer that enforces domain logic.
The problem was in my approach to testing. I tried to use managers to set up test data. I now do it directly using repositories and there's no need for hacks like IDDQD roles and such.
So, basically, I use repositories to populate databases with test data, and then I hit managers to test domain logic in them.
I have a project that has the following requeriments:
Allow users to login in the same Web Application using different schemas following a criteria;
Dynamically route the datasource against a rule - for example, users in Company A should access schema A, users in Company B should access schema B;
The business logic which authenticates the user`s should be in a business component - EJB, because new applications can be added and this logic must be outside the Web Application.
I read about using Dynamic Data Source Routing. The CustomerContextHolder has a field which is ThreadLocal. Is ThreadLocal a guarantee that the user A will access the schema A following my criteria? Will the code be thread safe?
The way i understand is that you need multi tenency for spring along with datasource.
Probably you have have a look to spring extension which might help
https://github.com/mariofts/spring-multitenancy