Change data source dynamically on user login - spring

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

Related

What is the best way to make Jhipster auto generated application have SAAS model?

Like Jhipster generated app has out of box user management, I want to create a company/organization concept in JHipster so that every data is associated with its own organization/company
What is the best approach to handle it?
Have someone done it before?
First, for the database you should look at multitenancy in Hibernate and precisely at the discriminator column approach described in
https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#multitenacy and https://www.baeldung.com/hibernate-5-multitenancy
Then, for the REST layer, you should consider implementing a Spring MVC interceptor to map authenticated user to tenant id. For debugging purpose, you should also consider setting the tenant id in logback MDC so that you can see it in logs.
Finally, you got to think at the admin part, administrators should probably be able to access all data from all tenants. If admins should not be allowed to do so, you should consider encrypting data with a key per tenant.
There's a blueprint but it's not working for current JHipster 7 and team is looking for contributors. However, there are examples generated that you could look at for inspiration, https://sonalake.com/latest/multi-tenant-applications-with-jhipster/

Handling Global Settings In Microservices

Supposed we had a couple of services service-1,service-2, service-3, we can handle global configurations like DB configs,environment configs etc using an externalized service like spring cloud config server or consul. But what is the best way to handle admin related settings in Micro-services e.g Max funding amount, vat, transaction limit etc setting that don't need a programmer to change ? note multiple services can use these values.
one way of doing this would be creating a bean which loads the data at the start of the app from db. In db you can have a table with admin privileges provide simple insert/update queries to the user who can/wants execute them. This user can be admin of the app who is using your app.
Other way would be creating your own properties/attributes and providing them in application.properties file. You can load those properties any of the beans which you think will need them.
eg (for spring boot):-
spring.max.transaction.limit -- in application.poperties
#Value("${spring.max.transaction.limit}")
private String transactionLimit; -- in the bean

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

Finer control over Spring Security on Spring Data REST

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)

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.

Resources