We have a SpringBoot based module, we have REST APIs which allow creating resources with Params like
POST /resources
{
"resourceName": "Res1",
"admins": ["john.doe@company.com", "jane.doe@company.com"]
}
{
"id": "R1"
"resourceName": "Res1",
"admins": ["john.doe@company.com", "jane.doe@company.com"]
}
POST /resources
{
"resourceName": "Res2",
"admins": ["alice@company.com", "bob@company.com"]
}
{
"id": "R2"
"resourceName": "Res2",
"admins": ["alice@company.com", "bob@company.com"]
}
For R1
update API should only be accesible by John/Jane
PUT /resources/R1
{
"resourceName": "Resource1",
"admins": ["john.doe@company.com", "jane.doe@company.com", "jacob@company.com"]
}
For John / Jane the response should be:
{
"id": "R1"
"resourceName": "Resource1",
"admins": ["john.doe@company.com", "jane.doe@company.com", "jacob@company.com"]
}
When Alice / Bob user are updating R1
this response should be 403 Forbidden
Similarly For R2
update API should only be accesible by Alice / Bob.
When John / Jane are updating R2
this response should be 403 Forbidden
Please suggest which framework can be used to achieve this, preferably with less boiler plate
Currently we have a system where resource access is in for of RoleBasedAccessControl. We achieve restriction by storing permissions. The RBAC config is saved in DB.
But now we need more fine grained control per resource which can be managed directly by existing admins
This can be achieved using a method level security from SpringBoot.
First enable Method Level Security by annotating a Config class like -
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class GlobalMethodConfig extends GlobalMethodSecurityConfiguration
Then provide an implementation of PermissionEvaluator
class like -
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, Object permission) {
if (permission.equals("RESOURCE_WRITE_AUTHORITY")) {
Resource res = resourceRepository.getResourceById((String) targetId);
if(env != null) {
return env.getAdmins().contains(authentication.getName());
}
}
return false;
}
After which you can annotate your PUT method in controller or the corresponding method in the service, to use PermissionEvaluator, like
@PreAuthorize("hasPermission(#resourceName, 'RESOURCE_WRITE_AUTHORITY')")
public Environment updateResource(String resourceName)