When should I implement Spring Security ACL in my application? - spring

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.

Related

Using Spring ACL in a complicated access setup for an entity

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

Spring session for session sharing(clustering) between servers

I'm trying to let two machines with the same base domain (subdomains differ) to share session.
spring-session-jdbc seems to be a solution I could use to achieve the goal.
When a user logs into server-a, session info is stored in SPRING_SESSION db.
What worries me is the fact that custom org.springframework.security.core.userdetails.UserDetails class is stored in that db as well.
When server-b tries to read session data from the db, it has to use the same custom subclass of the org.springframework.security.core.userdetails.UserDetails.
So I'm copying codes that relates to the UserDetails class from server-a to server-b.
I'm feeling a little awkward doing this, because server-a and server-b might want different UserDetails in general.
Is this really intended way of using spring-session-jdbc ?
Another question is, is it mandatory to use spring-security for both server-a and server-b?
Spring Session is meant to easily enable session clustering, i.e. have the multiple instances of the same app share the external session store therefore making it easier to scale your app.
For the problem you are trying to solve it might be a good idea to use an appropriate higher level protocol such as OAuth 2.0 and OpenID Connect and implement single sign-on without coupling you applications through the session store.
While the idea of sharing session store between different apps might seem convenient initially, such arrangement is usually very problematic, as you noted yourself with the UserDetails example.
In line with Vedran Pavic's answer it sounds like you should be using sso. That said there are instances where different code bases may want to share the same session such as in micro-service clusters. In this case you should simply put your UserDetails into a base jar/module that the other jar/module's are dependent upon. You can use a build automation tool to make this packaging easier to accomplish.
To answer your final question, if these two applications are regularly communicating with each other then I'd recommend either using spring security everywhere or nowhere.
Default mechanism to persist and load session is through the SecurityContextRepository (Spring Security) or SessionRepository (Spring Session).
If you use Redis for session sharing the repository implementation could be RedisSecurityContextRepository (spring-security-redis) or RedisIndexedSessionRepository (Spring Session).
The latter one for sure serialize UserDetails so you cannot share the session unless you use same Frameworks & user classes versions.
I would use custom SessionRepository and store shared user info in portable Json or XML, or whatever you like, not the Java object serialized ))

Spring Security Domain Model Authorization

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

Is there a way to bypass all security checks in Spring Security?

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.

Spring MVC Custom Authentication

What I am looking to accomplish is a filter (or similar) that would handle the authentication model for my Spring MVC application. My application is also hosted on Google App Engine.
The authentication on this application can tend to be very dynamic and the permissions are not something that would fit cleanly into a predefined Role structure. These permissions would be tied to the different action methods on my controllers. Ideally I would like to be able to annotate these permissions but I am open for other suggestions.
I am finding that there is not very much information around on how to accomplish this. Ideally I would like to be able to intercept the call to my controller actions and be able to read off the annotations and handle accordingly. What I am hoping is that someone here has a little bit more knowledge on Spring MVC and where I can inject some custom code, and would be able to point me in the right direction.
I would still use Spring Security to do this. It may not have a class that 100% fits your login scheme, but that's what inheritance is for. Write your own. You can easily get rid of the ROLE based DecisionManager and make it fit your paradigm.
Based on your comments have you checked out the MethodInterceptor in Spring? It creates a Proxy that will intercept calls to any method on the proxied class and allow you to run or disallow the method based on any code you want. In Spring Security there is an AbstractSecurityInterceptor, but I find it very hard to use and for most access decisions I think it's overkill.
So I would use Spring Security to authenticate the user (and populate the SecurityContext) and then use interceptors to wall off access to methods in your controllers that you want protected.

Resources