Keycloak integration

Any experience with integrating Keycloak for authentication and authorization?
I guess that authorization should be handled by Spring Boot, but are there any recommendations or examples for implementing authorization on command and query processors?

1 Like

That is an interesting question.

Did you mean to ask how to implement such features in a custom application?

Or are you looking for a some generic framework extension that helps with that? I mean would you want for example the framework to provide some sort of authentication and authorisation API that’s easy to use from commands/events/queries and allows to plug in different providers like Keycloak?

Either way it would be great if you can elaborate a bit more about how you envision authentication and authorisation should work?

Some example might be nice, but those things tend to become very specific quickly. Like is any authorised used allowed to issue queries, but you might need specific roles for commands?

I think it would be nice if you could set some roles on the @CommandHandler or @EventHandler methods. Just typing my thoughts here, I don’t have any experience on authorization combined with Axon.

That is true. In fact authorisation tend not only to get specific but also very complex. That’s why I was asking for more details. I would really like to understand the actual use case(s).

Generally speaking (and somewhat oversimplifying) what is needed is to be able to answer the question “Can a SUBJECT perform an ACTION on a OBJECT?” for any SUBJECT, ACTION and OBJECT combination. If I understand correctly, the intention is to use a dedicated solution (Keycloack) to maintain the rules that answer those questions. If so, before we start discussing implementation details related to the actual integration, there are some design challenges to be solved.

  • who owns the auth data (subjects, actions, objects, …) and who owns the rules and thus answers? Is it the same system?
  • are the rules applied to infrastructure components (“can send message”, “can process command”, …) or are they applied on domain data (“managers can see salaries of the people they manage”) or both?
  • what is the relationship model between the application and the auth system (anticorruption layer, conformist, shared Kernel, customer-supplier, …)?
  • when should the auth questions be asked (during message dispatching, processing, routing, handling, …)?
  • …

IMHO just looking at those base points it becomes clear that trying to address complex security checks on a framework level will be too much. But perhaps there is something that the framework can do to make the integration easier or provide some abstractions or extensions for most common cases, … In that sense I find the question interesting.

I guess many people here have implemented auth in one form or another so it would be interesting to hear about your experiences, solutions and thoughts.

I am somewhat late to the party but can suggest how such a check might be implanted in the framework.

Axon internally uses things called HandlerEnhancerDefinitions to “add” behavior to message handling functions. I’ve put “add” between quotes because it is, in essence, the basis for all the behavior message handling functions have in Axon.

For example, the @SagaEventHandler sets and validates the associationProperty through a dedicated HandlerEnhancerDefinition. Likewise, the routingKey on the @CommandHandler annotation works with a dedicated HandlerEnhancerDefinition.

So, if you want to attach forms of security validation to command and query handling methods, providing a HandlerEnhancerDefinition would be the way to go. I have seen this being done at users of the framework, who constructed a custom security annotation. Axon reacted to those if they were paired with the @CommandHandler and/or @QueryHandler annotated method.

As a follow-up, you might think, “why isn’t this a part of Axon?” For that, I’d point to Milen’s earlier reply. There are quite some application-specific things to consider here, making it rough to construct a generic solution that suits everybody’s needs. I am not going to rule it won’t be a part of the framework eventually, however. For now, though, it’s something you’ll have to construct yourself.

1 Like