[keycloak-user] API Authorization: on request or response?

Corentin Dupont corentin.dupont at gmail.com
Wed Nov 15 08:00:23 EST 2017


Thanks.
Is it possible to define this policy "Only the Owner Can Access" in
Keycloak UI? Should I use a Javascript policy?

On Wed, Nov 15, 2017 at 12:48 PM, Pedro Igor Silva <psilva at redhat.com>
wrote:

> Yes, that is correct. When you create a resource via admin console, the
> owner is always the resource itself. The resource can be considered as a
> "common" or "general" resource, managed and owned by the resource server
> itself.
>
> When using the API, you can set the owner to any user you want (we have a
> JIRA to also allow to set owner to a group), which means the resource
> belongs to that  particular user.
>
> Your question is very pertinent and allows me to clarify an interesting
> behavior when permissions are evaluated for a given user. When you ask
> permissions for a particular user (where the user's identity is represented
> by the access token you send to both Entitlement or Authorization APIs)
> Keycloak will evaluated permissions based on the resources owned by the
> resource server (the general resources) plus the ones that belong to the
> user.
>
> When you set the owner to an user you can write policies like "Only the
> Owner Can Access" as you can check if the identity seeking access
> (represented by the access token) is the same as the owner of a resource.
>
>
>
> On Wed, Nov 15, 2017 at 9:11 AM, Corentin Dupont <
> corentin.dupont at gmail.com> wrote:
>
>> Sorry to disturb again, another small question:
>> It seems that with the Keycloak UI I cannot choose the owner of a
>> resource, but with the API I can? Is that correct?
>> Thanks
>>
>> On Tue, Nov 14, 2017 at 9:43 PM, Pedro Igor Silva <psilva at redhat.com>
>> wrote:
>>
>>> In the first case you should get an error instead. Will check the second
>>> case as in theory it should just ignore the scope.
>>>
>>> On Tue, Nov 14, 2017 at 2:32 PM, Corentin Dupont <
>>> corentin.dupont at gmail.com> wrote:
>>>
>>>> I spotted something strange:
>>>> If I try with a non existing resource:
>>>>
>>>> $ curl -X POST -H "Content-Type: application/json" -H "Authorization:
>>>> Bearer $TOKEN" -d '{
>>>>     "permissions" : [
>>>>         {
>>>>             "resource_set_name" : "xxx",
>>>>             "scopes" : [
>>>>                 "view"
>>>>             ]
>>>>         }
>>>>     ]
>>>> }'  "http://localhost:8080/auth/realms/waziup/authz/entitlement/waziup"
>>>>
>>>> It replies with 200:
>>>> {"rpt":"eyJhbG...}
>>>> Is this correct?
>>>>
>>>> If I try also with a non existent scope (yes I'm nitpicking):
>>>>
>>>> $ curl -X POST -H "Content-Type: application/json" -H "Authorization:
>>>> Bearer $TOKEN" -d '{
>>>>     "permissions" : [
>>>>         {
>>>>             "resource_set_name" : "xxx",
>>>>             "scopes" : [
>>>>                 "xxx"
>>>>             ]
>>>>         }
>>>>     ]
>>>> }'  "http://localhost:8080/auth/realms/waziup/authz/entitlement/waziup"
>>>>
>>>>
>>>> It replies with 500: Internal Server Error
>>>>
>>>> On Tue, Nov 14, 2017 at 2:13 PM, Corentin Dupont <
>>>> corentin.dupont at gmail.com> wrote:
>>>>
>>>>> This works great, thanks.
>>>>>
>>>>> TOKEN=`curl -X POST \
>>>>>     -H "Content-Type: application/x-www-form-urlencoded" \
>>>>>     -d 'grant_type=client_credentials&client_id=myclient&client_sec
>>>>> ret=myclientsecret'
>>>>>     "http://localhost:8080/auth/realms/${realm_name}/protocol/op
>>>>> enid-connect/token" | jq .access_token -r`
>>>>>
>>>>> Then I do:
>>>>> $ curl "http://localhost:8080/auth/realms/myrealm/authz/protection/
>>>>> resource_set" -H "Authorization: Bearer $TOKEN"
>>>>> ["037f5d3e-8f25-4af1-93a0-4e17455d0614"]
>>>>> $ curl "http://localhost:8080/auth/realms/myrealm/authz/protection/
>>>>> resource_set/037f5d3e-8f25-4af1-93a0-4e17455d0614" -H "Authorization:
>>>>> Bearer $TOKEN"
>>>>> {
>>>>> "name": "Sensors",
>>>>> "uri": "/sensors/*",
>>>>> "type": "http://localhost:3000/sensors",
>>>>> "scopes": [
>>>>> {
>>>>> "id": "da776461-c1f5-4904-a559-1ca04d9f53a9",
>>>>> "name": "view"
>>>>> },
>>>>> {
>>>>> "id": "2615157c-f588-4e2b-ba1c-720fe8394215",
>>>>> "name": "manage"
>>>>> }
>>>>> ],
>>>>> "owner": "0892e431-5daf-413e-b4cf-eaee121ee447",
>>>>> "_id": "037f5d3e-8f25-4af1-93a0-4e17455d0614",
>>>>> "id": "037f5d3e-8f25-4af1-93a0-4e17455d0614"
>>>>> }
>>>>>
>>>>> Next I tried to POST a new resource:
>>>>> curl -X POST "http://localhost:8080/auth/re
>>>>> alms/waziup/authz/protection/resource_set" -H "Content-Type:
>>>>> application/json" -H "Authorization: Bearer $TOKEN" -d '{
>>>>> "name": "My house",
>>>>> "uri": "/houses/123",
>>>>> "scopes": [
>>>>> {
>>>>> "id": "da776461-c1f5-4904-a559-1ca04d9f53a9",
>>>>> "name": "view"
>>>>> },
>>>>> {
>>>>> "id": "2615157c-f588-4e2b-ba1c-720fe8394215",
>>>>> "name": "manage"
>>>>> }
>>>>> ],
>>>>> "owner": "0892e431-5daf-413e-b4cf-eaee121ee447"
>>>>> }'
>>>>>
>>>>> Everything seems OK.
>>>>>
>>>>>
>>>>> On Tue, Nov 14, 2017 at 1:44 PM, Pedro Igor Silva <psilva at redhat.com>
>>>>> wrote:
>>>>>
>>>>>> Try this:
>>>>>>
>>>>>> curl -X POST \
>>>>>>     -H "Content-Type: application/x-www-form-urlencoded" \
>>>>>>     -d 'grant_type=client_credentials&client_id=myclient&client_sec
>>>>>> ret=myclientsecret'
>>>>>>     "http://localhost:8080/auth/realms/${realm_name}/protocol/op
>>>>>> enid-connect/token"
>>>>>>
>>>>>> Without BASIC but credentials as form parameters.
>>>>>>
>>>>>> On Tue, Nov 14, 2017 at 10:37 AM, Corentin Dupont <
>>>>>> corentin.dupont at gmail.com> wrote:
>>>>>>
>>>>>>> Thanks, actually I saw it but I didn't understand where this bit
>>>>>>> came from: aGVsbG8td29ybGQtYXV0aHotc2VydmljZTpwYXNzd29yZA==
>>>>>>>
>>>>>>> On Tue, Nov 14, 2017 at 1:20 PM, Pedro Igor Silva <psilva at redhat.com
>>>>>>> > wrote:
>>>>>>>
>>>>>>>> The problem here is that you got an access token (that you are
>>>>>>>> using as a bearer to access Protection API) using resource owner password
>>>>>>>> grant type (direct grant). That means the subject of the token is an user
>>>>>>>> (username) and not the resource server itself.
>>>>>>>>
>>>>>>>> Only resource servers (your client application) are allowed to
>>>>>>>> access the Protection API (and managed resources).
>>>>>>>>
>>>>>>>> The access token you got is valid to query for permissions though.
>>>>>>>> As you want to obtain a set of permission an user has. Where the token
>>>>>>>> represents user identity.
>>>>>>>>
>>>>>>>> You should fix that error by obtaining a access token for your
>>>>>>>> client. Something like that (from docs):
>>>>>>>>
>>>>>>>> curl -X POST \
>>>>>>>>     -H "Authorization: Basic aGVsbG8td29ybGQtYXV0aHotc2VydmljZTpwYXNzd29yZA==" \
>>>>>>>>     -H "Content-Type: application/x-www-form-urlencoded" \
>>>>>>>>     -d 'grant_type=client_credentials' \
>>>>>>>>     "http://localhost:8080/auth/realms/${realm_name}/protocol/openid-connect/token"
>>>>>>>>
>>>>>>>>
>>>>>>>> On Tue, Nov 14, 2017 at 7:47 AM, Corentin Dupont <
>>>>>>>> corentin.dupont at gmail.com> wrote:
>>>>>>>>
>>>>>>>>> Thanks for the documentation, after reading it I found that I can
>>>>>>>>> use "entitlement" endpoints for my use case.
>>>>>>>>> So I do:
>>>>>>>>>
>>>>>>>>> TOKEN=`curl -X POST  -H "Content-Type:
>>>>>>>>> application/x-www-form-urlencoded" -d
>>>>>>>>> 'username=username&password=password&grant_type=password&cli
>>>>>>>>> ent_id=myclient&client_secret=myclientsecret' "
>>>>>>>>> http://localhost:8080/auth/realms/myrealm/protocol/openid-c
>>>>>>>>> onnect/token" | jq .access_token -r`
>>>>>>>>>
>>>>>>>>> curl -X POST -H "Content-Type: application/json" -H
>>>>>>>>> "Authorization: Bearer $TOKEN" -d '{
>>>>>>>>>     "permissions" : [
>>>>>>>>>         {
>>>>>>>>>             "resource_set_name" : "Houses",
>>>>>>>>>             "scopes" : [
>>>>>>>>>                 "view"
>>>>>>>>>             ]
>>>>>>>>>         }
>>>>>>>>>     ]
>>>>>>>>> }'  "http://localhost:8080/auth/realms/myrealm/authz/entitlement
>>>>>>>>> /myclient"
>>>>>>>>>
>>>>>>>>> Is this correct? It seems to be working.
>>>>>>>>> I am not sure how can I get/create resources via the API.
>>>>>>>>> I tried:
>>>>>>>>>
>>>>>>>>> curl "http://localhost:8080/auth/realms/myrealm/authz/protection/
>>>>>>>>> resource_set" -H "Authorization: Bearer $TOKEN"
>>>>>>>>> But I get:
>>>>>>>>> {"error":"invalid_clientId","error_description":"Client
>>>>>>>>> application with id [2ecfae24-f340-4ad0-a12e-02cdc60cd8ba] does
>>>>>>>>> not exist in realm [myrealm]"}
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Mon, Nov 13, 2017 at 6:11 PM, Corentin Dupont <
>>>>>>>>> corentin.dupont at gmail.com> wrote:
>>>>>>>>>
>>>>>>>>>> Hi again,
>>>>>>>>>> I looked everywhere but I couldn't find an Evaluation API for
>>>>>>>>>> javascript...
>>>>>>>>>> In my nodeJS server, should I call UMA API endpoints?
>>>>>>>>>>
>>>>>>>>>> On Mon, Nov 13, 2017 at 12:34 PM, Pedro Igor Silva <
>>>>>>>>>> psilva at redhat.com> wrote:
>>>>>>>>>>
>>>>>>>>>>> Hi,
>>>>>>>>>>>
>>>>>>>>>>> It seems you are looking for fine-grained permissions. Could you
>>>>>>>>>>> take a look at this example [1] and documentation [2] ?
>>>>>>>>>>>
>>>>>>>>>>> One of the things shown by that example is how to protect
>>>>>>>>>>> resources based on its owner.
>>>>>>>>>>>
>>>>>>>>>>> [1] https://github.com/keycloak/keycloak/tree/master/example
>>>>>>>>>>> s/authz/photoz
>>>>>>>>>>> [2] http://www.keycloak.org/docs/latest/authorization_servic
>>>>>>>>>>> es/index.html
>>>>>>>>>>>
>>>>>>>>>>> On Sun, Nov 12, 2017 at 7:14 PM, Corentin Dupont <
>>>>>>>>>>> corentin.dupont at gmail.com> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Hi guys,
>>>>>>>>>>>> another small question :)
>>>>>>>>>>>>
>>>>>>>>>>>> Suppose you have an API looking like this:
>>>>>>>>>>>> http://www.example.com/api/v1/cars
>>>>>>>>>>>>
>>>>>>>>>>>> Cars have an owner:
>>>>>>>>>>>> {
>>>>>>>>>>>>   name: "my car"
>>>>>>>>>>>>   owner: "smith"
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>> How to make sure that you can only get cars that are yours (you
>>>>>>>>>>>> can have
>>>>>>>>>>>> several cars)?
>>>>>>>>>>>> If you make a simple GET on this endpoint, should I:
>>>>>>>>>>>> 1. just reply with a "Access denied" because the request is too
>>>>>>>>>>>> large: it
>>>>>>>>>>>> could yield cars that are not yours,
>>>>>>>>>>>> 2. reply with "Access denied" if the response list contains
>>>>>>>>>>>> some cars that
>>>>>>>>>>>> are not yours,
>>>>>>>>>>>> 3. filter the response car list with only yours?
>>>>>>>>>>>>
>>>>>>>>>>>> It seems that 1. is the simplest because it uses only the
>>>>>>>>>>>> request to make
>>>>>>>>>>>> decisions.
>>>>>>>>>>>> 2. uses the response to make decision, while 3. requires the
>>>>>>>>>>>> collaboration
>>>>>>>>>>>> of the response handler in my API server, in order to implement
>>>>>>>>>>>> the
>>>>>>>>>>>> filtering.
>>>>>>>>>>>> What is the most standard way?
>>>>>>>>>>>>
>>>>>>>>>>>> I have also some trouble understanding how to implement that
>>>>>>>>>>>> with Keycloak
>>>>>>>>>>>> protect in NodeJS.
>>>>>>>>>>>> Cheers!!
>>>>>>>>>>>> Corentin
>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>> 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