The problem
If you’re using memcached for session management in your Spring Boot application and you’re also using Keycloak Spring Boot adapter, you might be googling right now because the Java Serialization does not work in your project. That is, either you’re getting an Exception with the message:
filter can not be set after an object has been read
or perhaps you noticed that your serialization filter does not work. Either all classes are allowed to be serialized, which creates a security issue, or only the Keycloak classes are allowed, which breaks your application because the sessions saved in memcached cannot be resumed properly.
What’s going on
The issue is that memcached session handler is deserializing a bunch of different classes at the same time. That is, in the same ObjectInputStream
. This happens because your session is composed by a number of different objects; so memcached serializes them one-by-one into its storage and then, the same way, it deserializes them back into your application. This works great until you deserialize an object of the class KeycloakSecurityContext
. That class introduces a filter in your ObjectInputStream
.
What happens after that is that the Keycloak Spring Boot adapter class is allowed and it keeps being deserialized correctly, but now suddenly all other classes are not allowed to be deserialized because keycloak excludes them by adding “!*” at the end of its filter.
Now you have a strong headache 😵 and you’re thinking “Enough bullshit, how do I fix this?”. I understand and I’ve got a bad headache as well, keep reading.
The solution
There are multiple solutions to this issue (good news! 😀) depending on how deep you dare (😣) go and change things in your application.
The correct™ solution is to make sure that KeycloakSecurityContext
objects (and any other class that introduces such filters) are deserialized in their own streams rather than in the same, common, stream.
If this is not possible in your project, you need to override the filter in KeycloakSecurityContext
by extending the class. If you’re choosing this path (fly, you fools 😈) you will have to edit the ObjectFilter
. The approach that I would think it’s most correct in this case is to completely remove the filter from KeycloakSecurityContext
and then add a filter at the application level where you define all the classes and the packages that you allow for deserialization in your application. Link on how to do it.
Another approach, a bit hacky but easier to test, is to add all the relevant classes in the filter in the class extending KeycloakSecurityContext
(try this for a quick test but please, don’t use it in production).
Conclusion
This is a bug, or let’s say a missing functionality, in memcached-session-manager
. In this article we lister several methods to work around the filtering problem that this issue creates. There is already an open ticket in memcached-session-manager‘s repository and hopefully there will soon be a new version that is completely compatible with Keycloak. 🤞