[keycloak-user] Authorisation services: resource server managing permissions
Fabio Berta
fnberta at gmail.com
Wed Mar 20 11:25:23 EDT 2019
Pedro Igor Silva <psilva at redhat.com> schrieb am Mi., 20. März 2019 um
15:32 Uhr:
> On Wed, Mar 20, 2019 at 10:54 AM Fabio Berta <fnberta at gmail.com> wrote:
>
>> Hi Pedro,
>>
>> Thank you very much for quick answer, very helpful!
>>
>> Pedro Igor Silva <psilva at redhat.com> schrieb am Mi., 20. März 2019 um
>> 14:08 Uhr:
>>
>>> Correction ... You can also push claims using node-js-adapter
>>> https://github.com/keycloak/keycloak-nodejs-connect/blob/master/test/fixtures/node-console/index.js#L172
>>> .
>>>
>>> On Wed, Mar 20, 2019 at 10:05 AM Pedro Igor Silva <psilva at redhat.com>
>>> wrote:
>>>
>>>>
>>>>
>>>> On Wed, Mar 20, 2019 at 9:36 AM Fabio Berta <fnberta at gmail.com> wrote:
>>>>
>>>>> Hi
>>>>>
>>>>> I have a couple of questions regarding Keycloak's authorisation
>>>>> services.
>>>>> Premiss:
>>>>> - I don't really need the whole user managed permissions and permission
>>>>> sharing features that UMA gives. All permissions are given by admin
>>>>> users.
>>>>> - My resource server is a NodeJS application, hence I cannot use the
>>>>> pre-made Java adapters
>>>>>
>>>>
>>>> Did you had a change to look the node-js-adapter [1] ?
>>>>
>>>
>> Yes, thanks! We actually used the node-js-adapter for inspiration in a
>> lot of cases when building our own custom adapter (which only supports a
>> small subset of the node-js-adapter and also does other things).
>>
>>
>>>
>>>> [1]
>>>> https://github.com/keycloak/keycloak-nodejs-connect/blob/master/test/fixtures/node-console/index.js#L156
>>>>
>>>>
>>>>> - I'm not sending RPT tokens to public clients at the moment, the
>>>>> resource
>>>>> server checks permissions by making a request to Keycloak
>>>>>
>>>>> Let's assume I want to protect the entity "Config". I need to restrict
>>>>> create/delete/update rights for all configs and read rights for every
>>>>> single instance of config. To achieve that, I created the the scopes
>>>>> "config:read", "config:create", "config:delete" and "config:update". I
>>>>> created the resource "config" and attached the scopes "config:create",
>>>>> "config:delete" and "config:update". Because only users with the realm
>>>>> role
>>>>> "admin" should be able to create/update/delete, I created a role based
>>>>> policy specifying the "admin" role and connected it with the resource
>>>>> "config" and the scopes "config:create", "config:delete" and
>>>>> "config:update" in a scope-based permission. So far everything is
>>>>> pretty
>>>>> straightforward and works well.
>>>>>
>>>>> Where it's get more complicated is the read rights for individual
>>>>> configs.
>>>>> What I have in mind is an interface where admins can create configs and
>>>>> manage permissions for them without going through the keycloak admin
>>>>> console. Whenever an admin creates a new config, the resource server
>>>>> creates a corresponding resource (e.g. config/configId) and stores the
>>>>> id
>>>>> of the resource next to the config. I can do that with Protection API
>>>>> (authz/protection/resource_set).
>>>>>
>>>>
>>>> Another approach to this problem would be to push claims to your
>>>> policies so you could avoid creating resources for every single config.
>>>>
>>>> For the Java-based adapter we have the concept of Claim Information
>>>> Points [1], which basically defines a repository from where the adapter
>>>> should obtain additional claims in order to push these claims to the server
>>>> along with an authorization request. You can also look here [2] for more
>>>> details about how to send these same claims directly to the token endpoint.
>>>>
>>>> With this approach, you would have a single "Config" resource and
>>>> specific permissions for both write (create/delete/update) and read
>>>> operations. For admin, you are fine as you just need a role-policy to check
>>>> if a user is granted with the admin role. But for read, you could write a
>>>> JS-policy [3] that matches the subject making the request with a specific
>>>> claim that your resource server is pushing to the server, where this claim
>>>> would contain the user ids or names, for instance. In a nutshell, you are
>>>> basically making your policy model more flexible so the resource server is
>>>> in charge to actually pass which users are allowed to access. The good side
>>>> of this is that it avoids you create resources in Keycloak. The bad side is
>>>> that your resource server is responsible to push this information, but
>>>> maybe this is something you already have in the RS.
>>>>
>>>> [1]
>>>> https://www.keycloak.org/docs/latest/authorization_services/index.html#_enforcer_claim_information_point
>>>> [2]
>>>> https://www.keycloak.org/docs/latest/authorization_services/index.html#_service_pushing_claims
>>>>
>>>>
>> Interesting, so this would mean that my resource server would need to
>> keep track of which users have access to wich config. My fear would be that
>> this logic could get complex quite fast when it has to track a mixture of
>> groups and users permissions (I would basically be re-implementing the
>> different policies keycloak offers I guess? Although currently only user
>> and group are relevant for us.). We also have multiple resource servers
>> which all talk to the same keycloak instance. If the resource server needs
>> to keep track of all permissions, I would need to have this logic in every
>> resource server. The beauty of having the resources in keycloak would be
>> that the resource servers would only need to store the resourceId for every
>> config (or any other entity) and nothing else. Or am I missing something?
>>
>
> Yeah, that is the bad side I mentioned. Just wanted to put another
> solution on the table.
>
> There is another one that may help with your problem too. Resources have
> attributes and you could use attributes to keep track of the list of users
> or groups that are allowed to access the resources. Then, in a JS policy,
> you could match subject vs users/groups in the resource's attribute.
>
That's another interesting suggestion, I will look into this, thanks!
>
>
>>
>> Follow-up question would be, is creating resources for every single
>> config a bad thing and would you in general advise against it? I assume the
>> list of resources would get very big over time but I don't know if that's a
>> problem? I guess it could be when I need to query keycloak for all
>> resources a user has access to in order to list them. If this is list is
>> huge, this could get costly at some point.
>>
>
> There is nothing wrong in managing a huge amount of resources in the
> server. The admin console should behave fine as well as policy evaluation.
> The policy evaluation should be optimized for processing permissions for a
> set of one or more resources (when you specify the resources/scopes in the
> authorization request), but a "give me all entitlements" approach may
> suffer a bit ...
>
Awesome, in that case I'm leaning towards going with the creating a
resource for every config. This seems like the cleanest solution to me and
would also make it easier to switch to a UMA flow if user managed
permissions should every become a requirement at some point in the future.
For the "give me all permissions" use case, I can always pass the
"config:read" scope as the permission param of the token query with
"urn:ietf:params:oauth:grant-type:uma-ticket" grant type. I think this
should keep the size of the returned list manageable.
>
> Maybe one thing we could do though is to also allow the resource server to
> have user-managed resources, where the user, in this case, would be the
> service account. That would simplify your use case a lot as you would just
> need to create the resource and use the Policy API (through a single API,
> the Protection API). But this is something that needs more discussion as we
> are quite moving out of the scope ...
>
Yes, that was basically what I had in mind when I tried using the Policy
API. If this is something you are considering, I'm happy to provide more
details on our use cases if that helps. For now I think I can achieve a
similar thing by using the Admin API for creating resources and permissions
as you suggested.
>
>
>>
>>
>>>
>>>>> What I have not yet figured out is how the resource server can set
>>>>> permissions at this point. Let's assume the admin has specified two
>>>>> users
>>>>> that should be able to access the new config. The resource server
>>>>> should
>>>>> create a new user based policy containing the two users and connect it
>>>>> with
>>>>> the "config/configId" resource and the scope "config:read" in a
>>>>> scope-based
>>>>> permission. From the documentation it looks like the Policy API might
>>>>> be
>>>>> able to handle this. But two things confuse me:
>>>>> - It says "This API is protected by a bearer token that must represent
>>>>> a
>>>>> consent granted by the user to the resource server to manage
>>>>> permissions on
>>>>> his behalf". I don't need to manage on the users behalf, the resource
>>>>> is
>>>>> owned by the resource server and the created permission would also be
>>>>> owned
>>>>> by the resource server.
>>>>> - The examples for the API somehow combine policies and permissions
>>>>> into
>>>>> one?
>>>>> I tried to use this API with a token obtained via the client
>>>>> credentials
>>>>> grant but it failed to create permissions (empty response and nothing
>>>>> got
>>>>> created).
>>>>>
>>>>> I see that the Java Admin Client has the ability to manage permissions
>>>>> but
>>>>> I can't find documentation on the REST endpoints it uses. (
>>>>> https://www.keycloak.org/docs-api/5.0/rest-api/index.html doesn't
>>>>> contain
>>>>> anything authz related). Would the Admin API be the thing to use here
>>>>> or
>>>>> can I do this with the Policy API? Or maybe my approach is
>>>>> fundamentally
>>>>> flawed and I should approach this from another angle?
>>>>>
>>>>
>>>> The Policy API is really for UMA protected resources. It is not an
>>>> option in your case.
>>>>
>>>> To achieve your goal, you would need the Admin API. We don't have it
>>>> documented because it is mainly used by our administration console. For
>>>> now, you could just capture the requests that the admin console is
>>>> performing to manage permissions and policies. The API provides a specific
>>>> endpoint for each policy/permission type as well a specific payload.
>>>>
>>>
>> I see, thanks! A related question, the admin console also uses the Admin
>> API to create resources. If I need to create resource in my resource
>> server, are there advantages in using the Protection API or shall I use the
>> Admin API for this case as well?
>>
>
> For your particular case, I think the Admin API. The reason is that you
> will also need to manage permission and policies and you probably want to
> avoid using two distinct APIs.
>
I see, make sense. Will switch to the Admin API then for managing
resources.
>
>
>>
>>
>>>
>>>>
>>>>>
>>>>> This message got way to long but I hope I was able to make my questions
>>>>> clear. Grateful for any help I can get!
>>>>>
>>>>> Best regards,
>>>>> Fabio Berta
>>>>> _______________________________________________
>>>>> keycloak-user mailing list
>>>>> keycloak-user at lists.jboss.org
>>>>> https://lists.jboss.org/mailman/listinfo/keycloak-user
>>>>>
>>>>
More information about the keycloak-user
mailing list