Currently I am writing my own custom @PreAuthorize annotation. My case is as follows,
- I am running my authorization KeyCloak server that holds the user details, roles and permission
- After Validation, I have stored the permission details in GrantedAuthority as follows "{rsname}:GET", "{rsname}:POST" ...
KeyCloak JWT permission structure:
"authorization": {
"permissions": [
{
"scopes": [
"GET",
"DELETE",
"POST"
],
"rsid": "6ae9895f-3766-464f-82c4-44f598ec2a93",
"rsname": "record"
}
]
}
- while using @PreAuthorize annotation in controller instead of hardcoding the resource name and scopes, we have to generalize it by getting the details from application.property we have achieved it as follows,
application.property:
auth:
data:
name1: record
name2: device
Property Detail Component class:
@ConfigurationProperties(prefix = "auth")
@Component
public class SecurityProperty {
private Map<String, String> data;
....
}
Controller:
@RequestMapping (method = RequestMethod.GET,value = "/api/records",
produces = {"application/json"})
@PreAuthorize ("hasAuthority (@securityProperty.getData(). get('name1') "
+ "+ ': GET')")
ResponseEntity<List<SomeDTO>> getRecords() {
...Some Logic
}
@RequestMapping(method = RequestMethod.GET,value = "/api/devices",
produces = { "application/json" })
@PreAuthorize("hasAuthority(@securityProperty.getResources().get('name2') "
+ "+ ':GET')")
ResponseEntity<List<SomeDTO>> getDevices() {
...Some Logic
}
- So far this is working fine. Since we are creating big project we don't want to write this lengthy @PreAuthorize(XXXX) annotation so decided to create custom annotation that uses the @PreAuthorize. We have created @CustomPreAuthorize as below
@Retention(RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@PreAuthorize("hasAuthority(@securityProperty.getResources().get(#resource)"
+ ".concat(':GET'))")
public @interface CustomPreAuthorize {
String resource();
}
And used this in controller
@RequestMapping (method = RequestMethod.GET,value = "/api/devices",
produces = {"application/json"})
@CustomPreAuthorize (resource = "name2")
ResponseEntity<List<SomeDTO>> getDevices() {
...Some Logic
}
Issue:
- When I used like this when the API is called I am getting the following error
Failed to evaluate expression 'hasAuthority(@securityProperty.getResources().get(#resource).concat(':GET'))"
- So far what I understood is like the resource and scope are not getting recognized in the @PreAuthorize annotation level. Is it possible to read the values like this or is there any alternatives available?