[keycloak-user] Support authorization for dynamic resources not saved in Keycloak resources DB, and querying for additional information from "PIP" service inside of policy

Pedro Igor Silva psilva at redhat.com
Mon Sep 10 12:06:49 EDT 2018


Hi,

AFAIK, you should be able to define URIs for resources like that:

  "/api/groups/{groupID}/events",
  "/api/groups/{groupID}/events/{eventID}",
  "/api/groups/{groupID}/events/{eventID}/subscribe",
  "/api/groups/{groupID}/events/{eventID}/unsubscribe"

And have specific permissions for each path/resource above.

Regarding the issue around making sure the user is indeed admin of a group,
you could probably push a claim obtained from an external service [1].
Another option could be implementing a custom CIP provider [2] as an
alternative to the http one in order to query your database.

What version of Keycloak are you using, btw ?

[1]
https://www.keycloak.org/docs/latest/authorization_services/index.html#obtaining-information-from-an-external-http-service
[2]
https://github.com/keycloak/keycloak/blob/035ebc881abfe78544861f394c30b1dd9623f879/adapters/oidc/adapter-core/src/main/resources/META-INF/services/org.keycloak.adapters.authorization.ClaimInformationPointProviderFactory

Regards.
Pedro Igor

On Mon, Sep 10, 2018 at 11:13 AM, Marcel Német <Marcel.Nemet at gmail.com>
wrote:

> It would be great to support dynamic resources using more complex Wildcards
> mechanism. It would be very useful for our company. But I will rather
> explain the use case on better-known use-case: Groups and Events on
> Facebook.
>
>
>
> Groups on Facebook have members and admins.  Groups are created and deleted
> often, and one user can be member and admin of multiple groups.
>
> Example:
>
> Group for hikers
>
> Admins: Alice, Adam
>
> Members: Mark, Michelle
>
>
>
> Group for dancers:
>
> Admins: Antoni
>
> Members: Martin
>
>
>
> Admins can create and delete events
>
> e.g. Hiking in Himalayas event
>
> Members can subscribe and unsubscribe from events
>
>
>
> The REST API might look like:
>
>
>
> GET api/groups/{groupID}/events/
>
> ·         Can be done by members or admins
>
>
>
> DELETE api/groups/{groupID}/events/{eventID}
>
> ·         Only by admins
>
>
>
> POST api/groups/{groupID}/events/{eventID}/subscribe
>
> ·         Here the danger is that Martin who is not a member of Group for
> hikers could manipulate the request and do:
>
> ·         POST
> api/groups/Group-for-dancers/events/Hiking-in-Himalayas/subscribe
>
> ·         So, it is not enough to check whether Martin is a member of the
> group in the request. It must also be checked that the Event belongs to
> that group.
>
>
>
> Or directly, without referencing the group
>
> POST api/events/{eventID}/subscribe
>
> In the second case, the system would have to check whether the user is a
> member of the group. This has to be queried from the facebook DB.
>
> POST api/groups/{groupID}/events/{eventID}/unsubscribe
>
>
>
> When the user subscribes to an event he can see it under
>
> GET api/user/{userID}/subscribedEvents/{eventID}
>
>
>
> And he can unsubscribe under
>
> POST api/events/{eventID}/unsubscribe
>
>
>
> ==============================
>
>
>
> Challenges in Keycloak:
>
> Currently, all the resources would have to be created in the Keycloak
> server one by one
>
> E.g.
>
> /groups/Group for hikers/events/Hiking in Himalayas
>
> ·         With scopes GET and DELETE
>
> /groups/Group for hikers/events/Hiking in Himalayas/subscribe
>
> /groups/Group for hikers/events/Hiking in Himalayas/unsubscribe
>
>
>
> And when the user subscribes to the event, another resource would need to
> be added
>
> /user/Mark/subscribedEvents/Hiking in Himalayas
>
> ·         With scopes GET
>
> /user/Mark/subscribedEvents/Hiking in Himalayas/unsubscribe
>
> /user/Michelle/subscribedEvents/Hiking in Himalayas
>
> ·         With scopes GET
>
> /user/Michelle/subscribedEvents/Hiking in Himalayas/unsubscribe
>
>
>
> And when the Mark and Michelle unsubscribe, the last resources should be
> removed. This adds additional overhead.
>
>
>
> The permissions can be then applied to the resource type if the resources
> are properly typed, this works well.
>
>
>
> If Keycloak supported dynamic URLs and multiple wildcards or parameters
> inside URI
>
> It would be possible to simply define general permissions for the API
> routes
>
> For example, it would be great to be able to define a resource with a
> wildcard parameter such as
>
> api/groups/{groupID}/events/{eventID}
>
> ·         With scope DELETE
>
> Then the permission could be added simply with a policy that permits the
> action if the user is admin of the group with ID {groupID}.
>
>
>
> Having to create resources in Keycloak resources DB is a drawback because
> it creates another single point of failure - we have a complicated system
> that is quite critical. Constantly creating and deleting resources is
> complicated. If at any time the synchronization between resource DB in
> Keycloak and our system fails, it would be very hard to recover.
>
>
>
> ======================================
>
> At the moment I see a workaround of using different REST API routes such as
>
> DELETE api/groups/events?groupID={groupID}&eventID={eventID}
>
>
>
> But this forces us to use sub-optimal paths which do not conform to the
> usually recommended syntax of REST APIs.
>
>
>
> Then I can define a resource in keycloak as
>
> api/groups/events/*
>
> With scope DELTE
>
>
>
> And inside policy enforcer I can push claim such as
>
> "event-delete-claim"="eventID : {request.parameter['eventID']}"
>
> Or even use the whole relative URI as a claim - adding a unique claim to
> the RPT makes sure that the user gains access only to single resources or
> group fo resources and not to all resources that match api/groups/events/*.
>
>
>
>
>
> Then in a permission for the resource "api/groups/events/*" with scope
> "DELETE" I must check somehow whether the user who is trying to call this
> API is admin of a group where the event is hosted. It is hard to know
> whether the event belongs to a group from such request since we cannot
> trust the information in the HTTP request even if group ID was part of the
> request. Here I would need to query the system DB with the eventID and get
> the groupID or even better directly list of the admins of the group to
> which the event belongs.
>
>
>
> =========================================
>
> Summary
>
> ·         It would be great to support dynamic resources with multiple
> wildcards/parameters so we do not need to sync all existing and newly
> created resources with the Keycloak DB
>
> ·         It would be great to be able to query external service from
> inside of a policy (e.g. something like Java Policy Provider (SPI?) with an
> ability to call a trusted Policy Information Point ("PIP") to get
> additional information necessary to make a decision)
>
> o    For example, the Policy "Allow if the user is an administrator of the
> group of the event" would be applied to the resource "DELETE
> api/groups/*/events/*". The policy code would be able to query some backend
> service and check that the event really belongs to the group and that the
> user is admin of that group.
>
>
>
> I would love to hear your thoughts on this, or whether any of the two
> propositions could be added or whether another strategy to achieve this
> exists.
>
>
>
> --
> Marcel Német
> marcel.nemet at gmail.com
> _______________________________________________
> 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