spring-session icon indicating copy to clipboard operation
spring-session copied to clipboard

Provide ClientHttpRequestInterceptor to pass Session along

Open pcornelissen opened this issue 6 years ago • 4 comments

In Microservice based applications especially, you have the task to do requests on behalf of the user.

With Spring session the behavior suddenly changed and the session is now base64 encoded. This leads to duplicated code and more "fun" when this changes again. So it's not feasible in the long run to add the sessionID in the right encoding by yourself in every service that depends on other services.

As the RestTemplate provides support for ClientHttpRequestInterceptors to modify the request it would be nice to be able to rely on a implementation that generates a cookie that is definitively the same that the spring session implementation is configured for.

Is there a chance that spring session ships such a ClientHttpRequestInterceptor?

pcornelissen avatar Jun 27 '18 07:06 pcornelissen

Thanks for the report @pcornelissen.

To begin with, I'd first like to address the following statement:

With Spring session the behavior suddenly changed and the session is now base64 encoded.

This isn't true. Neither session nor session id by themselves are being encoded in any way. What is being Base64 encoded by default starting with Spring Session 2.0 is the value of session cookie. Note that this concern is specific to cookie based implementation of HttpSessionIdResolver (or HttpSessionStrategy in Spring Session 1.x).

As stated in the #1016 (comment), assuming that the raw value of session cookie matches the raw value of session id is fragile. To provide an example of this, see Multiple HttpSessions in Single Browser feature that we had in Spring Session 1.x. Note that due to refactoring of session id resolution mechanism we did in Spring Session 2.0, this feature was removed but will likely be reintroduced at some point (see #917). Such use case was actually the driver for use to use Base64 encoding for session cookie by default - see #605 and this [Stack Overflow question].(https://stackoverflow.com/questions/38687210/error-with-cookie-value-when-adding-a-new-spring-session)

Having said that, there are actually several options for you:

  • as stated in #1016 (comment), you can very easily restore the previous behavior (i.e. not having session cookie value Base64 encoded) by registering your own DefaultCookieSerializer bean and setting useBase64Encoding to false
  • perhaps even better, you could use HTTP header based HttpSessionIdResolver implementation (i.e. HeaderHttpSessionIdResolver) for your API and have client simply pass the session id in an HTTP header - see HttpSession & RESTful APIs section of reference manual
  • provide a custom HttpSessionIdResolver implementation that fits you the best

However with you describing your use case with the task to do requests on behalf of the user I believe this perfectly fits OAuth2 protected resource, so that gives you another option, although more complicated to implement if you're not employing OAuth2 in some form already.

Regarding ClientHttpRequestInterceptor proposal, I'm not sure if we would recommend that approach over the ones listed above.

vpavic avatar Jul 03 '18 20:07 vpavic

Hi Vedran, thanks for your long answer. You are right I wanted to type that the sessionID is now base64 encoded, not the session itself.

I know that I can create my own HttpSessionIdResolver, but it's a bad user/developer experience when I have to add and configure that in all microservices, so I'd rather stick to the default behaviour if possible. By now I have fixed the behaviour in my services and it's OK, but I'm afraid for the next change ;-)

Regarding the OAuth suggestion, I tried that approx 2 years ago and got stuck somewhere, found spring session and it worked fine until now, so oauth is not yet required (although I want to give it a try again when I find the time)

I can see that you might be reluctant to add the Interceptor to your codebase, but I think it would help to easily create solutions that utilize multiple services in the backend. It's OK to close this issue, it was just a suggestion, because I imagine that there are more prople with this problem.

pcornelissen avatar Jul 04 '18 17:07 pcornelissen

Thanks for following up @pcornelissen.

You are right I wanted to type that the sessionID is now base64 encoded, not the session itself.

Again, this isn't correct and that's the point I was trying to make in my previous - session id itself is not Base64 encoded, only the value of session cookie is. As I tried to show through Multiple HttpSessions in Single Browser feature, session cookie value isn't always equal to session id, so it's fragile to rely on that.

Anyway, going back to 3 options suggested in previous comment, I understand that implementing your own HttpSessionIdResolver might not be the most attractive solution so putting that and OAuth2 aside, I'm curious why the first two (setting useBase64Encoding to false or using HeaderHttpSessionIdResolver) don't suit you?

We'll leave the ticket open to give it some thought.

vpavic avatar Jul 05 '18 12:07 vpavic

Argh, you're right again (of course). As I don't use multisessions, this is effectively the same for me, but you're right, this is not something that you fully can rely on. Which makes my initial request even more important. It's just too error prone to have everyone reinvent and recode the session passing in the restTemplates.

As I said the custom configured ID resolver is not very feasible when you are creating 15-20 services, so it has a high value to stick to the defaults. This leaves OAuth2, which at least when I tried had no obvious good tutorials that helped to use it as it brings a lot of complexity to the configuration and request flows compared to simply passing the session and enabling spring-session. This may have changed, but I didn't stumble upon a tutorial yet that was complex enough to be more than hello world and simple enough to not go full in a heartbeat ;-)

pcornelissen avatar Jul 05 '18 12:07 pcornelissen