Mantelo - A Keycloak Library That Guarantees Completeness

Mantelo - A Keycloak Library That Guarantees Completeness

Introducing Mantelo - The Best Keycloak Admin Client for Python

Lucy Linder, a fervent technologist and software engineer, unveiled a new open-source project Mantelo, designed as a compact yet powerful Python library interacting with the Keycloak Admin API.

In comparison to an older and more popular python-keycloak library maintained by 100+ contributors, the author guarantees her library will always maintain completeness without modification.

Born from the frustration of encountering incomplete support in existing libraries, this is the only Python client that guarantees full coverage of all the routes in the Keycloak Admin RESTful API. How? By wrapping instead of implementing.

I am aware wrapping instead of implementing has a drawback: if Keycloak changes the Admin API, your code has to be updated (no encapsulation).

This design philosophy has the effect of transferring the burden of validation and error handling in the code downstream to the developer using the library.

But I believe it is a small price to pay, especially since Keycloak proved to be careful about retro-compatibility.

At its core, mantelo leverages the slumber library, an object-oriented wrapper for the requests library, that showcases the benefits of late binding. This approach enables mantelo to postpone HTTP calls, similar to how duck typing delays method calls. A late binding occurs when there is a delay in the resolution until runtime, as methods and attributes are decided during execution rather than at compile time.

You'll find many different definitions of duck typing out there. At its core, this coding style is based on the a well-known saying:

If it walks like a duck and quacks like a duck, then it must be a duck.

Extrapolating to OOP, a duck type is where an object is considered compatible with a given type if it has all the methods and attributes that the type requires.

class Ostrich:
    def walk(self):
        print("The ostrich is walking")

class Duck:
    def walk(self):
        print("The duck is walking")
    def fly(self):
        print("The duck is flying")

In this example, the two birds can walk, but only the Duck can fly. Although they are completely independent classes, they share the same method walk. Hence you can use them in a flexible style.

birds = [Ostrich(), Duck()]

for bird in birds:
    bird.walk()

The output is as follows:

The ostrich is walking
The duck is walking

If you try to add bird.fly() in the for loop, you will get an AttributeError: 'Ostrich' object has no attribute 'fly'.

We know that ostriches cannot fly, but if we want to have the other birds fly in the code, we can create an empty method for the Ostrich as follows:

class Ostrich:
    def walk(self):
        print("The ostrich is walking")
+   def fly(self):
+       return

The result is as follows:

The ostrich is walking
The duck is walking
The duck is flying

But I digress, let's take an example of how you manage users with the mantelo library.

# GET /admin/realms/{realm}/users
adm.users.get()
# GET /admin/realms/{realm}/users?search=foo+bar
adm.users.get(search="foo bar")
# GET /admin/realms/{realm}/users/count
adm.users.count.get()
# GET /admin/realms/{realm}/users/110
adm.users("110").get()

Instead of implementing methods to reach endpoints, mantelo uses simple rules to translate Python code to HTTP calls.
Every request returns either the content of the response's body (parsed from JSON) or an instance of HttpException if the response's status code is not in the 2XX range.

Let's assume that the Keycloak Admin API changes in the future for its users/count endpoint to users/length:

# GET /admin/realms/{realm}/users/count
adm.users.count.get() # your code breaks

The mantelo library does not know what API endpoints exist, and the burden falls on you for knowing how to translate the API endpoints from HTTP calls to Python code.

Despite the potential modifications required due to API changes, and the transfer of code validation and error handling downstream, the library has several benefits:

  1. mantelo's footprint is ridiculous: it is currently less than 1000 lines of code and has only 3 direct dependencies.

  2. mantelo is the only library that can rightfully claim it supports the whole Keycloak Admin interface and is always up-to-date.

  3. mantelo abstracts away authentication (and refresh tokens), which is always tricky to get right.

  4. mantelo gives you access to the exact URL that was called (or the requests.Response in case of an error) so debugging is easy.

  5. mantelo is flexible: you can tweak it easily if you need to.

After weighing both mantelo's benefits and weaknesses, you can explore using either mantelo or python-keycloak as a library in your next project.