I am trying to get familiar with the Authorization Services concepts from Keycloak by playing around with the app-authz-rest-springboot from Keycloak-Quickstarts.
I run a keycloak-server and the app-authz-rest-springboot locally, following the guidelines and they work as expected. However, I face an issue when I try to add a new endpoint to the app and secure it as the other endpoints that are provided in the app-authz-rest-springboot.
What I try to do is to forward the request body of an HTTP request to the policy-enforcer of keycloak's client and decide if the request should be granted based on the request body.
On the application side I have the following:
- The new endpoint:
@PostMapping("/api/example")
public String exampleEndpoint(@RequestBody RequestDto requestDto) {
System.out.println(requestDto.getUserId());
return createResponse();
}
- The request body for the endpoint:
public class RequestDto {
public String userId;
public RequestDto() {}
public RequestDto(String userId) {
this.userId = userId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
@Override
public String toString() {
return "RequestDto{" + "userId=" + userId + '}';
}
}
- The policy-enforcer-config to push the request body to the keycloak-policy-enforcer for the permission evaluation of the endpoint
keycloak.policy-enforcer-config.paths[3].path=/api/example
keycloak.policy-enforcer-config.paths[3].claimInformationPointConfig.claims[user.id]={request.body['/userId']}
On the keycloak-server side:
- A Resource called Example Resource binding
/api/example
(the aforementioned endpoint) - A custom js policy, which prints the request-body of the endpoint to stdout and always grants the request.
var context = $evaluation.context;
var attributes = context.attributes;
print(attributes.getValue('user.id').asString(0));
$evaluation.grant();
- A Permission that binds the Example Resource(1) with the custom js policy(2)
I make a request to the application using Postman with a request-body:
{
"userId": "blablabla"
}
The custom js policy script prints the request body
10:37:46,387 INFO [stdout] (default task-6) blablabla
Which means that the application pushes correctly the request body to the policy-enforcer. Additionally, keycloak grants the request successfully.
Although, on the application side, after the keycloak's policy enforcer interception, the request fails with a 400 Bad Request
HTTP status and a response:
{
"timestamp": "2021-11-25T08:37:46.454+0000",
"status": 400,
"error": "Bad Request",
"message": "Required request body is missing: public java.lang.String org.keycloak.quickstart.springboot.web.ApplicationController.exampleEndpoint(org.keycloak.quickstart.springboot.web.RequestDto)",
"path": "/api/example"
}
It seems like the policy enforcer from keycloak somehow "removed" the request body from the request after the permission evaluation. It is weird because as I mentioned, the claims have been successfully pushed to the keycloak and the request has been successfully granted.
Does anyone have faced a similar issue? Or is there any post or example online which I can follow? I googled it a lot but unfortunately, I haven't found anything yet. And, the keycloak-quickstarts do not provide any similar example pushing the request body to the policy-enforcer. The examples are limited in showing how to forward request parameters to keycloak.