[keycloak-user] Authorisation services: resource server managing permissions
Pedro Igor Silva
psilva at redhat.com
Wed Mar 20 10:32:46 EDT 2019
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.
>
> 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 ...
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 ...
>
>
>>
>>>> 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.
>
>
>>
>>>
>>>>
>>>> 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