I had a similar use-case, where the admins might want to create new roles, with arbitrarily assigned permissions to these roles.
If I were to authorize users on the existence of a ROLE_*
in their granted authorities, then the code would need to change every time someone adds a new role, or the business requirements for that role changes.
Like @Ralph, I created a library to inject mapped authorities based on Role to Permissions
because I found the hierarchical role implementation lacking...
When an Authentication object is injected in the current security session, it will have the original roles/granted authorities.
You can provide map the permissions in your UserDetailsService, or JWT Authentication Converter for instance.
The PermissionProvider is called to get the effective permissions for each role the user is a member of. The distinct list of permissions are added as GrantedAuthority items in the Authentication object.
Then I can use permission level authorization in the configuration, and the role to permission mapping can change at runtime.
Concept -
ADMIN1 -> PERM_ADD, PERM_POST
ADMIN2 -> PERM_POST, PERM_UPDATE
Implementation example -
@Autowired
RolePermissionsRepository repository;
public void setup1(){
String roleName = "ROLE_ADMIN1";
List<String> permissions = new ArrayList<String>();
permissions.add("PERM_ADD");
permissions.add("PERM_POST");
repository.save(new RolePermissions(roleName, permissions));
}
public void setup2(){
String roleName = "ROLE_ADMIN2";
List<String> permissions = new ArrayList<String>();
permissions.add("PERM_UPDATE");
permissions.add("PERM_POST");
repository.save(new RolePermissions(roleName, permissions));
}
Then use the permissions for access instead of roles.
<http auto-config="true">
<intercept-url pattern="/addData" access="PERM_ADD" />
<intercept-url pattern="/updateData" access="PERM_UPDATE" />
<intercept-url pattern="/postMessage" access="PERM_POST" />
</http>
Or using the authorization annotations -
@PreAuthorize("hasAuthority('PERM_ADD')")
@RequestMapping("/add")
public String add() {
...
}
For the source code, see here -
https://github.com/savantly-net/spring-role-permissions