[keycloak-dev] Securing realm resources with custom admin roles
Dmitry Telegin
mitya at cargosoft.ru
Fri Aug 19 20:12:36 EDT 2016
Hi,
While developing a complex production-grade KeyCloak extension I've
faced the following problem. Let's say the extension provides several
custom realm resources plus the relevant parts of admin console GUI. A
user should be able to access this functionality only if he/she has
corresponding roles: one role for read-only access, another one for
full operation. The "domain-extension" example does solve the similar
problem, but in a very simplistic way: the user is only checked against
the built-in "admin" role. A real-world example would likely feature at
least two custom roles, different from the built-in ones. Implementing
this with the current KeyCloak version turned out to be a rather
complex problem. To demonstrate it, I've created the following example.
Throughout the example, two custom roles are used, "view-hello" and
"manage-hello":
https://github.com/dteleguin/custom-admin-roles
The problem could be broken down into three parts:
1. Creating roles. Imagine the instructions: "After you have installed
the extension, please go to Clients, select the master-realm client,
add view-hello and manage-hello roles, then go to Roles, select admin,
add the above roles to it. Repeat for each and every realm you've
already created, but this time also with the realm-management client
and realm-admin role. Don't forget to do the same for every new realm
you add" - this is totally unacceptable if we are speaking of high
quality software. In the example, this is fully automated (see
HelloResourceProviderFactory::postInit). Adding roles to the newly
created realms has become possible with the recent introduction of
RealmPostCreateEvent.
2. Client-side authorization. The GUI elements in the admin console
should be shown only to the users having corresponding roles. There is
the global "access" AngularJS object, instantiated by GlobalCtrl and
used everywhere in the admin console; it would be quite natural to use
the same semantics for custom roles. In the example, AngularJS
decorator mechanism is used to augment the "access" object with
additional getters, reflecting custom role grants. Unfortunately, by
some reason decorating GlobalCtrl directly doesn't work, so we have to
decorate all the controllers (as "$controller") and then select
GlobalCtrl. I'm not sure if it's a KeyCloak or AngularJS issue, since
there's not much information on the net about using decorators with
GlobalCtrl.
3. Server-side authorization, i.e. checking user roles in service
methods of realm REST resources. This is particularly cumbersome, and
imposes an ugly restriction on resource methods - all of them are
required to have @Context HttpHeaders in the argument list. Otherwise
it would be impossible to extract a JWS token and to deduce a realm to
authorize against. The only workaround I see is to move all the service
methods into a sub-resource, so that processing HttpHeaders and auth
setup could be done once, while instantiating sub-resource (like this
is done in o.k.services.resources.admin.AdminRoot). This is especially
frustrating because any custom realm resource is a sub-resource by
default, so there is no reason why it couldn't obtain a HttpHeaders
object from its parent resource upon construction.
Conclusion: a simple and natural requirement for an extension, which is
to have custom admin roles, turns into a lot of boilerplate code, most
of which is present in either form in KeyCloak. Could this
functionality be simply exposed to extensions? Ideally, this should be
a one-liner for extension authors, since the only information needed is
the name of the role(s). I could see it like this:
- an extension declares the roles. Considering possible introduction of
@KeyloakProvider annotation, this could be an annotation parameter, or
a separate annotation;
- KeyCloak takes responsibility for creating roles in both existing and
newly added realms;
- GlobalCtrl augments the "access" object with the relevant getters;
- upon creation, realm resources receive
an o.k.services.resources.admin.AdminAuth-like object, which could be
further decorated, or used as is.
What do you think?
Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/keycloak-dev/attachments/20160820/662fd257/attachment.html
More information about the keycloak-dev
mailing list