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

Federico Michele Facca federico.facca at martel-innovate.com
Fri May 11 09:19:42 EDT 2018


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 <https://github.com/keycloak/keycloak-quickstarts/tree/latest/app-authz-uma-photoz>.
> 
> If you look this method:
> 
>     https://github.com/keycloak/keycloak-quickstarts/blob/latest/app-authz-uma-photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java#L100 <https://github.com/keycloak/keycloak-quickstarts/blob/latest/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/client/src/main/java/org/keycloak/authorization/client/resource/PermissionResource.java#L162 <https://github.com/keycloak/keycloak/blob/master/authz/client/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”
    },



> 
> 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.

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-connect/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).

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.

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. 

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.

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/ <https://www.martel-innovate.com/>>  -  Professional
> support for innovation projects
> Click to download our innovators' insights!
> <https://www.martel-innovate.com/premium-content/ <https://www.martel-innovate.com/premium-content/>>
> Follow Us on Twitter <https://twitter.com/Martel_Innovate <https://twitter.com/Martel_Innovate>>
> _______________________________________________
> keycloak-dev mailing list
> keycloak-dev at lists.jboss.org <mailto:keycloak-dev at lists.jboss.org>
> https://lists.jboss.org/mailman/listinfo/keycloak-dev <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