Best practices for applying Spring Security for domain object authorization

Note: I’ve done a fair amount of research so far, including reading Spring Security in Axon and its preceding posts & issues linked therein.

We’re going to need to secure our domain instances using Spring Security. Can anyone point me to either an example where Spring Security is being used to authenticate commands and queries against particular aggregates, or advise me on best practices to configure this?

I suspect that likely integration points might be CommandDispatcherInterceptor, CommandInterceptor, etc, but Spring Security in Axon concludes with a suggestion about CorrelationDataProvider. That article is quite old (2015), so I’m not sure what has changed in the latest version of Axon.

Any advice would be appreciated. Thanks!

–Matthew

Hi Matthew,

what we did some time ago successfully is pretty much the solution you suggested: we implemented a MessageDispatchInterceptor that serializes the current Authentication from the SecurityContext to the Message Metadata prior to message dispatching and a MessageHandlerInterceptor that deserializes the Authentication again from the Message Metadata if present and puts it into the SecurityContext of the current thread prior to message handling.

This works well for Command dispatching and handling and allows to annotate CommandHandlers with Spring Security @PreAuthorize etc. annotations for securing domain instances.
For the query side it depends on how you serve the projections. Since we do not (yet) use axon queries I can’t say for sure but I guess the same pattern as for the command handling should apply.

What we implemented additionally (independently from Axon) was Spring Security ACL to get more fine-grained access control per domain object instance. For this we have implemented an EventHandler both on the command and query side that writes write (command side) and read (query side) ACLs based on processed create/delete events. This allows more fine-grained access control in the spring security authoization annotations like @PreAuthorize("hasPermission(#entityId, "com.acme.my.EntityType", 'DELETE')") which would check that the Principal currently authenticated in the Security context has ‘DELETE’ permission on the entity of type com.acme.my.EntityType with the identifier that comes in the entityId argument of the annotated method.

Best regards,
Jakob

1 Like