16

spring-security-oauth2 saves the Authentication object as part of the access token entry in the database as a serialized java object (ByteArrayOutputStream.writeObject(authentication)).

How do you handle version upgrades of either spring-security (which may change the SpringSecurityCoreVersion.SERIAL_VERSION_UID) and spring-security-oauth (which may change the serialVersionUID of the OAuth2Authentication)? If the serialVersionUID changes, the persisted Authentication object cannot be deserialized anymore.

We are coming to the conclusion that deleting the access tokens containing the serialized Authentication objects would be the cleanest and easiest solution when upgrading the framework version. Any ideas how to handle this more gracefully?

James
  • 11,654
  • 6
  • 52
  • 81
  • 2
    There's no better migration path that I am aware of. Access tokens are meant to be ephemeral - clients know how to get a new one if the one they have is invalid. – Dave Syer Dec 10 '14 at 11:25
  • @DaveSyer, could this be solved by not using Java serialization and serializing these objects to JSON or storing them using JPA instead? I see that the difficulty there would be in serializing complex inheritance hierarchies like org.springframework.security.core.Authentication or org.springframework.security.core.authority.Authority so I wonder if it is even worth trying to implement something like this. – Dmitry Chornyi Oct 02 '15 at 01:25
  • The problem is that you'd need to serialize every possible `Authentication` implementation to JSON - also the ones you do not have under control. With Jackson you could use mixins to do that, but every new `Authentication` implementation you use would require some work. We are currently thinking about using [Kryo](https://github.com/EsotericSoftware/kryo) to serialize it. It is much more resilient to model changes then the normal Java serialization. – James Oct 02 '15 at 09:01
  • did it work with Kryo? Facing similar issue here :) – hi_my_name_is Aug 01 '16 at 08:50
  • It works out so far, yes. But you need to keep in mind that Kryo is not able to serialize and deserialize just *any* object out of the box as the java serialization is. So you need a proper test setup to be sure to test the serialization and deserialization of *all* the classes involved (like `Authentication` and `UserDetails` implementations). – James Aug 02 '16 at 07:11

1 Answers1

2

I think that the best solution is to throw the tokens away. There is a big comment next to the declaration of SpringSecurityCoreVersion.SERIAL_VERSION_UID that says this:

/**
 * Global Serialization value for Spring Security classes.
 *
 * N.B. Classes are not intended to be serializable between different versions. See
 * SEC-1709 for why we still need a serial version.
 */

Indeed, they deliberately bump SERIAL_VERSION_UID (at least) on every minor release.

(The issue comments for SEC-1709 explain how they came to this solution.)

What I get from the comments is that if you did attempt to handle version upgrade transparently, you may cause things to break, with unpredictable consequences. (That is "code" for possible security problems.)


On the other hand, OAuth2Authentication.serialVersionUID doesn't appear to have changed in the last 9 years.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216