[keycloak-dev] How to share a resource with a user via UMA 2.0 API

Pedro Igor Silva psilva at redhat.com
Fri May 11 12:05:45 EDT 2018


Btw, just noticed we are discussing this in keycloak-dev. Could you please
move discussion to keycloak-user mailing list ?

On Fri, May 11, 2018 at 1:04 PM, Pedro Igor Silva <psilva at redhat.com> wrote:

>
>
> On Fri, May 11, 2018 at 10:19 AM, Federico Michele Facca <
> federico.facca at martel-innovate.com> wrote:
>
>> Hi Pedro,
>>
>> Thanks a lot for your quick reply.
>>
>> On 11 May 2018, at 13:52, Pedro Igor Silva <psilva at redhat.com> wrote:
>>
>>>
>>>
>> We don't have API documented, something we should improve in the future.
>>
>> We have a quickstart that can help you to achieve what you want. See
>> https://github.com/keycloak/keycloak-quickstarts/tree/
>> latest/app-authz-uma-photoz.
>>
>> If you look this method:
>>
>>     https://github.com/keycloak/keycloak-quickstarts/blob/late
>> st/app-authz-uma-photoz/photoz-restful-api/src/main/java/
>> org/keycloak/example/photoz/album/AlbumService.java#L100
>>
>>
>> I have been looking at the methods, and actually learned from the exact
>> example you refer to.
>>
>>
>> You will see that we are using the Permission Endpoint (the endpoint
>> responsible for managing permission tickets) to obtain all resources
>> *shared* with a specific user. In our AuthZ Java Client we have this method:
>>
>>     https://github.com/keycloak/keycloak/blob/master/authz/cli
>> ent/src/main/java/org/keycloak/authorization/client/resource
>> /PermissionResource.java#L162
>>
>> Which allows you to query for permission tickets using different filters.
>>
>>
>> Maybe my examples were not clear enough. For question 2:
>>
>>
>> Suppose that user "test" owns resource A and he want to see (like in the
>> my account interface) a table with all the active and pending permissions
>> including the identifier of the user that made the request.
>>
>> Shared resources->
>>
>> Resource A user B scope read, write
>>
>> Pending requests->
>>
>> Resource A user C scope read
>>
>>
>> With the following query:
>>
>> curl --request GET \
>>   --url 'http://127.0.0.1:8080/auth/realms/master/authz/protection/
>> permission?returnNames=true&owner=test' \
>>   --header 'authorization: Bearer xxx'
>>
>> I get a list of the permissions (where granted = true are the authorised
>> ones and granted = false the pending ones):
>>
>> [
>>     {
>>         "id": "08dccaed-6dbb-47aa-a87c-55b35a6f2523",
>>         "owner": "567c20ad-7d42-4908-bb53-af26c64534e7",
>>         "resource": "218091a8-e5fc-460c-a306-a3a76775c784",
>>         "scope": "65e40351-bce4-4e3f-825d-7bca9d78d12e",
>>         "granted": true,
>>         "scopeName": "read",
>>         "resourceName": "8910"
>>     },
>>     {
>>         "id": “xxxx",
>>         "owner": "567c20ad-7d42-4908-bb53-af26c64534e7",
>>         "resource": "218091a8-e5fc-460c-a306-a3a76775c784",
>>         "scope": "65e40351-bce4-4e3f-825d-7bca9d78d12e",
>>         "granted": false,
>>         "scopeName": "read",
>>         "resourceName": "8910"
>>     }
>> ]
>>
>> so the result does not allow me to know who was the “requester” (which I
>> don’t know apriori since the query is about all potential requesters)
>>
>
>>
>> so my idea was that when you use returnNames=true parameter you could add
>> as well the requester, e.g.:
>>
>>     {
>>         "id": "08dccaed-6dbb-47aa-a87c-55b35a6f2523",
>>         "owner": "567c20ad-7d42-4908-bb53-af26c64534e7",
>>         "resource": "218091a8-e5fc-460c-a306-a3a76775c784",
>>         "scope": "65e40351-bce4-4e3f-825d-7bca9d78d12e",
>>         "granted": true,
>>         "scopeName": "read",
>>         "resourceName": “8910”,
>>         “requester”:”xxxxx”,
>> “requesterName”:”test”
>>     },
>>
>
> I see now. We are really missing *requester* in the response. Not sure why
> it is not there already ....
>
> Created https://issues.jboss.org/browse/KEYCLOAK-7337.
>
>
>>
>>
>>
>>
>> The type PermissionResource also provides methods for CRUD permission
>> tickets.
>>
>> Note that this API is targeted for resource servers and part of the
>> Protection API.
>>
>>
>>
>> We realised that by trying to create resources and seeing that using user
>> authentication you get 500 error while using client authentication it works
>> (even though UMA specs is not limiting the access to that).
>> We found out by testing also that the permission endpoint works also with
>> user access tokens.
>>
>
> Yeah, as long as the access token is granted with uma_protection scope.
>
>
>>
>> Now the first question was how to “share” directly a resource with a user.
>>
>> Currently using the API, supposing I am user A and I want to access a
>> resource Z from user B, we proceed as follow (i hope is the correct way…
>> any correction or guidance will be appreciated):
>>
>> 1.  We create a permission request on the API (to get the ticket). E.g.
>> read resource x
>>
>> 2.  We use the ticket to ask for a rtp token using a user token.
>>
>> curl --request POST \
>>   --url http://127.0.0.1:8080/auth/realms/master/protocol/openid-con
>> nect/token \
>>   --header 'Authorization: Bearer xxx' \
>>   --header 'Content-Type: application/x-www-form-urlencoded' \
>>   --data 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Auma-
>> ticket&ticket=xxxx'
>>
>> If the user has already access, then he gets the rtp, if not he gets:
>>
>> {
>>     "error": "access_denied",
>>     "error_description": "request_submitted"
>> }
>>
>> Only in this moment the permission ticket i created at step 1 appears in
>> the list of permissions. (I am not sure this is the intended behaviour
>> though).
>>
>
> Yeah, that is the expected behavior. But you can also use a request
> parameter to tell to the token endpoint that you don't want to submit an
> authorization request. See https://www.keycloak.org/
> docs/latest/authorization_services/index.html#_service_authorization_aat.
>
>
>>
>> Then is up to the owner to authorise access (via API we can do that by
>> updating the permission and set granted to true)
>>
>> Now let’s suppose that I am the owner of the resource A, and I want to
>> authorise directly (without the user asking access to the resource A)
>> the user Z to access it. How can I do that? At the time being I could not
>> figure it out.
>>
>
> Similar to the update method, you can use the create method to create
> permissions. Is that what you are looking for ? See org.keycloak.testsuite.
> authz.PermissionManagementTest#testCreatePermissionTicketWithResourceName.
>
>
>>
>> Also, out of curiosity is there are a way i can list all resources i can
>> access thanks either to UMA permission or policies?
>> That would be very handful.
>>
>
> You can do that by asking all permissions. See https://www.keycloak.org/
> docs/latest/authorization_services/index.html#_service_
> obtaining_permissions.
>
> There is an cURL example there similar to this:
>
> curl -X POST \
>   http://${host}:${port}/auth/realms/${realm}/protocol/openid-connect/token \
>   -H "Authorization: Bearer ${access_token}" \
>   --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket"
>
>
> In the example above you are basically, saying that you want a RPT for any
> resource/scope granted to the user as a result of evaluating permissions
> associated with resources which the either the user or resource server is
> the owner. But yeah, depending on how many resources you will get a huge
> RPT which can take some time to be issued.
>
>
>>
>> Suppose that you have an API that with GET /resources list you all the
>> resources, there should be a way to filter the returned resources
>> only based on the one you can access. This could be done easily if you
>> could get a list of the resources you can access. Otherwise,
>> you would need for each resource returned in the list to generate a query
>> asking if the user x can access the specific resource. Not very
>> scalable.
>>
>
> We don't have anything for data protection. You are not the first with
> this requirement but I did not spend time thinking about this capability
> yet. If you want to open a JIRA and start some discussion there I'm glad to
> move this forward.
>
>
>>
>> Thanks!
>> Federico
>>
>>
>>
>>>
>>> In our understanding, to obtain 2. we should some how retrieve the
>>> Requester from the TicketStore and attach the information to the response
>>> (but this would "break" the UMA standard, as anyhow parameters as
>>> "returnNames=true" do, so maybe when the request is using
>>> "returnNames=true"
>>> we could attach as well the requester name and it).
>>>
>>> For 1, we have no clear ideas, if not adding "requester" as well in the
>>> ticket creation.
>>>
>>> Any hint would be highly appreciated, so that we can work up some
>>> implementation to provide both features.
>>>
>>> Thanks,
>>> Federico
>>>
>>> --
>>> *Dr. FEDERICO MICHELE FACCA*
>>> *Head of Martel Lab*
>>> 0041 78 807 58 38
>>> *Martel Innovate* <https://www.martel-innovate.com/>  -  Professional
>>> support for innovation projects
>>> Click to download our innovators' insights!
>>> <https://www.martel-innovate.com/premium-content/>
>>> Follow Us on Twitter <https://twitter.com/Martel_Innovate>
>>> _______________________________________________
>>> keycloak-dev mailing list
>>> keycloak-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/keycloak-dev
>>
>>
>> *Dr. FEDERICO MICHELE FACCA*
>> *Head of Martel Lab*
>> 0041 78 807 58 38
>> *Martel Innovate* <https://www.martel-innovate.com>  -  Professional
>> support for innovation projects
>> Click to download our innovators' insights!
>> <https://www.martel-innovate.com/premium-content/>
>> Follow Us on Twitter <https://twitter.com/Martel_Innovate>
>>
>>
>


More information about the keycloak-dev mailing list