Fine grained permission - View only if in same user group

Hey guys, I’m having trouble finding a solution for my use-case so I was hoping maybe someone more experienced could help me.
I have a keycloak instance in which I store all the employees of company. I’ve divided them in user groups which represent teams, every team has 1 member with role “team-lead”, others are simply “team-member”.
[e.g
Team x: UserX1 (team-lead), UserX2(team-member), UserX3(team-member),
Team y: UserY1(team-lead), UserY1(team-member),UserY3(team-member).
]
On my resource server which is spring boot application, I store feedbacks for employees.
What I want to do is to secure endpoint /feedbacks/{uid} (returns all feedbacks for certain user) so that only your “team-lead” can get your feedback, but if I do it role-based the problem is that team-lead of team Y will be able to get feedback for employee from team X because he also has the same role “team-lead”.
I guess I could have a logic in spring-boot app which will do this check but I was wondering if it is possible to do something like this by using Policies in keycloak?

hi, I’ll try.

The clean OAuth way to do this would be:

  1. resource server gets request with JWT
  2. resource server calls Keycloak (as PMP & PDP) with JWT and required resource
  3. Keycloak calls any other service to get any information it needs to evaluate policies
  4. Keycloak evaluates policies
  5. Keycloak returns permissions (either a simple yes/no, or more detailed)

The API is here: Authorization Services Guide (keycloak.org) / Obtaining Permissions

The policy would probably be a JavaScript policy, which would:

  • get the current user from the JWT
    • it can get the user’s group from the IDP (Keycloak itself), or you can put the group in the JWT and then get it from there
  • get the resource from the request, get the author from the resource, get the group of the author from the IDP (Keycloak itself)
    • alternately, store the author’s group with the resource/feedback, but I don’t favor this because it’s not as generic
  • compare groups and decide if they are the same

The problem you have is that the resource/feedback is created dynamically: if you want every feedback to have an author in the resource model, you’ll have to add all feedbacks to Keycloak, which means duplicating the whole feedback DB. Not practical.
So the remaining problem is to get the information “what group is the author of the feedback” to the evaluating policy.

I guess for that the solution is to use the claims parameter, and pass either the author of the feedback or their group, or even better the resource/feedback id in the resource DB.
If you pass in the claims parameter the id of the feedback, then Keycloak evaluation JS would call your feedback DB and get the owner and group. Which I think is good.

The whole point of the exercise is that the resource server doesn’t know about policies, and that some admin can edit the policies without knowing about the resource server. That’s why I also suggested passing the feedback id: the policy could then be amended to just about anything, size of feedback, language, etc.

If you need some JavaScript policy code I can provide some indications. I find the docs hard to locate and use.

1 Like

also : this is typically an UMA problem, so maybe just search for instructions on how to enforce UMA policies

(I’ll admit I never really found how to actually declare property of a resource in Keycloak)

Thanks for the reply, it was really helpful, I appreciate it very much!

I think I understand the flow now and how it should be done, I’ll try to implement it and get back to this thread and give feedback for future readings. I have one additional open question right now though:

Lets say I have API feedbacks/1, which returns all feedbacks given for employee 1, as resource (where 1 is uid), so when the request for this resource comes, my feedback service will call keycloak to check whether the user asking for it has permission or not. I am just wondering is it possible to do following things

  1. send this uid from resource server to keycloak and access it in my javascript policy
  2. get the user by id from my keycloak database in policy

If these are possible then I would say I just need to create js policy which will get the user based on uid and compare if it is in the same group as the user asking for resource which I already have.