Grails - Spring Security - Many dynamic roles - spring

I'm developing an application using Grails and Spring Security.
My wish is, when the user creates his account informing his company name, the app creates an entry in the company, role and user tables and relates that role and user with the company entry.
The role created will be like an administrator which has permission for do every thing. This user with that role can creates new roles specifying the permissions but all roles created should be only in the company scope, so those roles should not be available for users of others companies.
I've seen that the Spring Security has a feature called Requestmap which for each URL, the application can specify the roles which will have access.
I don't know if this is the best solution, because in my app the number of roles will increase at least as many as the number of user.
Do you guys have some advice of how to solve this problem?
Thank you for all.

You should have a look on Spring Security ACL plugin.
With this plugin you would be able to add permissions (like write or read permission) to certain users on certain domain models.
Have a look on example taken from documentation:
#Transactional
#PreAuthorize("hasPermission(#report, write) or " +
"hasPermission(#report, admin)")
Report updateReport(Report report, params) {
report.properties = params
report.save()
report
}
By using PreAuthorize annotation it is checked if user has write (or admin) permission on this certain Report entity.

Related

Spring Security: Creating multiple entry point for securing different rest controllers

I'm exploring the Spring framework, and in particular I am working on a Cinema Management Application that will be connected to a React.JS SPA (Single Page Application).
The problem is the following. On my database I do have three different tables representing three different types of users, namely Admin, Customer, and Cinema_Employee.
For each type of user, I created a #RestController with a list of RequestMethods that a particular user is able to perform:
"/admin"
"/customer"
"/employee"
What I am trying to achieve now, it's to secure each endpoint offering three different login pages that will handle the authentication the respective type of user.
How can I set up three AuthenticationManager that handle different Authentication objects within a SecurityConfig class given these requirements, and most importantly, how can I override the Authorisation mindful that each user once has logged in, will have access only to the respective endpoint?
I looked carefully at other examples online, and most of them are radical different, following a pattern where the database has another additional 'Authorities' table aside the 'user' one that stores the credential. In my case this solution cannot be applied, not only because the whole design would become redundant, but also because the name of the table where the application will perform the authentication check against, explicitly imply the authorisation that a given user has inside the system.
Your design sounds strange to me.
A user should have a role, e.g. Admin, Customer, Employee and based on the user's role he gets access to methods or not. Have a look at role based access control concepts. For Spring Security there is for example this tutorial:
https://www.baeldung.com/role-and-privilege-for-spring-security-registration

Keycloak resource protection recommendations

I'm writing web services in Spring Boot and I use Keycloak to protect the application. The app will expose API to manage restaurants.
In Keycloak I have two roles: admin and manager.
A user with admin role can CRUD restaurants. The same company has multiple restaurants and each restaurant has a manager. I want users with manager role to be able to edit only their restaurant (the restaurant they manage).
According to my understanding of Keycloak's documentation I have to use Resource with Permission but they stated that:
[] you can also have a different resource named Alice’s Banking Account, which represents a single resource owned by a single customer, which can have its own set of authorization policies.
To do that I have to create a resource like this /api/restaurants/12345 but the thing is that I can't hardcode an ID like this.
For now I protected my endpoint like this in spring boot:
http
.authorizeRequests()
.mvcMatchers(HttpMethod.PUT, "/api/restaurants/*").hasAnyRole("ADMIN", "MANAGER")
.anyRequest().permitAll();
This means that any manager from any restaurant can edit another restaurant. I want to limit that to their restaurant only (the restaurant they manage). How can I do that in Keycloak if at all possible?
What you are looking for is User managed access (UMA). It allows to manage the access permission for each resource.
The permissions can be managed with the user's authentication. So if a user enters a new restaurant you can automatically grant access permissions to him without involving a process with elevated privileges.
The best introduction is probably the Photoz example. Instead of restaurants, it's about photo albums.

Outsystems:Is it possible to have same user in different tenants in a Multi-tenant application

I created a multi-tenant application where each tenant have different set of users. I am trying to implement a functionality where same user might exist in different tenants. Does outsystems provide such functionality or I have to create my custom logic ?
Right now, I did create a user having same username in 2 different tenants and during login I am showing user to select tenants. But on changing tenants and logging to that tenant, the environment doesn't switch to that tenant that user has selected.
Below is the image of the logic of switching tenants and logging in the customer.
During debugging I saw that after executing TenantSwitch action it did change the Site.TenantID property but after User_Login action is reverted to the first tenant not the one user selected.
When you use User_Login(), the system will log you in the first Tenant it finds in the DB that has that username, thus ignoring your TenantSwitch().
So, if you want to login to a specific Tenant in your case, you need to be more explicit and instead use the Login() action - after the tenant switch.
For a thorough explanation of this, with example code, please check out the following deepdive Master Class on Multi-Tenancy starting around the 27:20 minute mark.
This isn't available out of the box as OutSystems assigns users (and all entities) to a specific tenant. Entities belonging to single tenanted modules are assigned to the default tenant.
OutSystems uses a hidden .Tenant_Id attribute on each entity to indicate which tenant that user belongs to. You can unhide this attribute for the users entity by selecting it, clicking More... and then ticking the relevant box in the Advanced tab. You can then access the attribute directly, but be aware this will hinder OutSystems' ability to do some of the stuff it does automatically to ensure that you access tenant specific data.
When you use the User_Login action OutSystems will deduce which tenant to use from the User.Tenant_Id attribute regardless of which tenant you've switched it to previously. The user would need an account for each tenant they need to use, but there's no reason this couldn't be done behind the scenes with OS fetching the correct username before logging in. You'd need to ensure they all stay in sync though, especially the passwords ofc.

Check user roles from Application Service

i'm implementing Application Service that sends statistical data to home page (dashboard application page).
Based on User's Role (the service needs authentication) i would extract/aggregate data from database using WhereIf() based on is role
In particular if user is administrator, I will not apply a data extraction filter using WhereIf()
To do that i've injected IAbpSession inside service constructor to be able to give userid, but how can i ckeck if user is an administrator?
You can check if current user is an administrator by checking the associated roles of that user. You must inject the UserManager which has several methods for role checking. One of them is IsInRole(userId, roleName).

Spring Security ACL extensions to support delegations

I am working on a Grails project that protects resources using Spring Security ACL plugin.
This application also allows resource owners to delegate permissions to other users and those users can further delegate their permissions to other users in viral fashion.
This works fine with standard Spring ACL API, but now I have new requirements:
Track who granted/delegated the given permission [User should be able to
see his/her permissions on a given resource as well as all other users
permissions that he/she delegated for that resource].
Control viral delegate by grantee by setting a flag to indicate if
this permission can be further delegatable.
I am planing to support those requirements by adding two additional fields [ 1. grantee (SID) , 2. isDelegatable ] to ACL_ENTRY table.
I wonder if it will impact any of the Spring ACL core functionality. How can I access those fields using standard Spring ACL API? Can I cast to custom Permission object and access those extended fields?
We are also planing to support time based expirable Permissions which are only applicable during given start and end time frame. where should I add this validation logic so that hasPermission() method call consider the time validity of the granted Permission?
Please advice.

Resources