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

Pedro Igor Silva psilva at redhat.com
Thu Nov 16 05:57:57 EST 2017


Yes. Or Rule Policy (Drools).

On Wed, Nov 15, 2017 at 11:00 AM, Corentin Dupont <corentin.dupont at gmail.com
> wrote:

> 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