7

What I am trying to achieve

Protect a resource in Keycloak with policy like:

if (resource.status == 'draft') $evaluation.grant(); 
else $evaluation.deny();

Going by their official documents and mailing list responses, it seems attribute based access control is possible, however, I could not find a way of getting it to work.

What I have tried

  • Using Authorization Services: I was unable to figure out where and how I can inject the attributes from the resource instance.
  • Using Authorization Context: I was hoping to get the policies associated with a resource and a scope so that I could evaluate them my self.

So far, I have managed to get no where with both approaches. To be honest, I have been overwhelmed by the terminology used in the Authorization services.

Question How can I use attributes of a resource instance while defining a policy in keycloak?

dubes
  • 5,324
  • 3
  • 34
  • 47
  • 3
    It looks like this is coming in Keycloak version 4. Already available in 4.0.0.Beta1 (see https://issues.jboss.org/browse/KEYCLOAK-6529). I did not try it out myself though – jadkik94 Apr 19 '18 at 21:47
  • Hey, it is an 18 version is up there, but I still don't see the attribute based policy, am I missing something? – Kostanos Jun 11 '22 at 09:59

2 Answers2

6

I solved this problem in Keycloak 4.3 by creating a JavaScript policy because Attribute policies don't exist (yet). Here is an example of the code I got working (note that the attribute values are a list, so you have to compare against the first item in the list):

var permission = $evaluation.getPermission();
var resource = permission.getResource();
var attributes = resource.getAttributes();

if (attributes.status !== null && attributes.status[0] == "draft") {
    $evaluation.grant();
} else {
    $evaluation.deny();
}
dave_erie
  • 197
  • 2
  • 8
  • Could you please clarify where does the `status` attribute value come from? Is it an attribute that is somehow set by the client or backend that requests access to it? If so, how can you forward this kind of information from the client / backend as a resource attribute? – Blink Apr 04 '19 at 14:15
  • Hi Dave, I knows it is old but I am also facing the same question. How did you get the status attribute? – NumeroUno Jun 20 '20 at 18:47
  • The resource attribute could be defined during resource definition, either done manually or through the resource API by the resource owner. In this approach the resource should actually represent an instance of your business object rather than its type (and probably use the keycloak's resource type attribute for generic type-level permissions if required), of course you'll need also to keep any custom resource attributes in-sync with any changes from their source of truth (i.e. resource owner). See https://www.keycloak.org/docs/latest/authorization_services/#_service_protection_api – Hesham Saleh Aug 30 '21 at 13:06
1

Currently there is no way to do what you are looking to do. ResourceRepresentation class only has (id, name, uri, type, iconUri, owner) fields. So you can use owner to determine ownership per Keycloak example. I've seen a thread that talks about adding additional resource attributes, but haven't seen a Keycloak JIRA for it.

Perhaps you could use Contextual Attributes in some way by setting what you need at runtime and writing a Policy around it.

var context = $evaluation.getContext();
var attributes = context.getAttributes();
var fooValue = attributes.getValue("fooAttribute");

if (fooValue.equals("something")) 
{
   $evaluation.grant();
}
Yev
  • 11
  • 1
  • Could you detail how to set Contextual Attributes at runtime? I don't find a parameter to set it at https://www.keycloak.org/docs/latest/authorization_services/#_service_obtaining_permissions – HFX Oct 14 '19 at 08:06